【数据结构】实验四:循环链表

实验四  循环链表

一、实验目的与要求

1)熟悉循环链表的类型定义和基本操作;

2灵活应用循环链表解决具体应用问题。

二、实验内容

题目一:有n个小孩围成一圈,给他们从1开始依次编号,从编号为1的小孩开始报数,数到第m个小孩出列,然后从出列的下一个小孩开始重新报数,数到第m个小孩又出列,……如此反复直到所有的小孩全部出列为止,求整个出列序列,例如:当n=6,m=5 时的出列序列是5,4,6,2,3,1 . 

题目二:围绕着山顶有10个洞,一只狐狸和一只兔子住在各自的洞里。狐狸想吃掉兔子。一天,兔子对狐狸说:“你想吃我有一个条件,先把洞从110编上号,你从10号洞出发,先到1号洞找我;第二次隔1个洞找我,第三次隔2个洞找我(第一次看1号洞,第二次看3号洞,第三次看6号洞),以后依次类推,次数不限,若能找到我,你就可以饱餐一顿。不过在没有找到我以前不能停下来。”狐狸满口答应,就开始找了。它从早到晚进了100次洞,也没找到兔子,请问,兔子可能躲在几号洞里,打印输出所有安全洞的编号。(使用一个循环单链表解决问题)

三、实验结果

1)请将调试通过的源代码粘贴在下面。(代码注意书写规范、主要模块要有功能注释)

题目一源代码:

#include <cstdio>
#include <malloc.h>
#include <iostream>
using namespace std;

typedef struct node{
	int no;//小孩编号
	struct node *next;		
}child;

//创建无头结点
void createlist(child *&head, int n){
	int i;
	child *p,*tail;//指向新建循环单链表的尾结点
	head=(child*)malloc(sizeof(child));
	head->no=1;//建立no为1结点的单链表
	tail=head;
	for(i=2;i<=n;i++){
		p=(child*)malloc(sizeof(child));
		p->no=i;//建立一个存放编号i的结点
		tail->next=p;
		tail=p;//将p结点链到末尾
	}
	tail->next=head;//构成一个首结点为head的循环单链表
}

//求出列顺序(约瑟夫问题) 
void joseph(int n,int m){
	//n->总数 m->出列数 
	int i,j; 
	child *head,*p,*q;
	createlist(head,n);//初始化列表 
	
	//出列n个小孩
	for(i=1;i<=n;i++){
		p=head; 
		j=1;
		//从head结点开始报数,报到第m-1个结点
		while(j<m-1){
			j++;//报数递增
			p=p->next;//移到下一个结点
		}
		q=p->next;//q指向第m个结点
		cout<<q->no<<" ";//该结点出列
		p->next=q->next;
		free(q);//删除q结点(出列结点) 
		head=p->next;//从下一个结点重新开始
	}
}

int main(){
	int n,m;//n->总数 m->出列数
	cin>>n>>m;
	joseph(n,m);
	return 0;
}

题目一结果展示:

 

 题目二源代码:

#include <cstdio>
#include <cstdlib>
#include <iostream>
using namespace std;

//创建结点 
typedef struct node{
    int a,b;//a为安全洞的标记,b为洞的序号
    struct node *next;
}node;

//主函数->find safe holes
int main(){
    node *p,*q;
    p=(node*)malloc(sizeof(node));
    p->b=1;
    p->a=1;
    q=p;//记录头结点 
     
    int i=0;
    while(i<9){
    	//创建十个结点 
        p->next=(node*)malloc(sizeof(node));
        p=p->next;//移动到下一个新结点 
        p->b=i+2;//洞的序号
        p->a=0;
        i++;
    }
    p->next=q;//构建循环 
    p=p->next;//回到头结点 
    
    //寻找安全洞并标记狐狸洞(进100次洞) 
    for(i=0;i<100;i++){
    	int j;
    	int temp=(i+2)%10;//序号归类为1-10 
        for(j=0;j<temp;j++){
            p=p->next;
        }
		p->a=1;//标记狐狸洞 
    }
    
    //输出安全洞 
    for(i=0;i<10;i++){
        if(p->a==0){
        	//非兔子洞已经进行标记 
        	cout<<"可能在第"<<p->b<<"个洞里面"<<endl;
		}
        p=p->next;//遍历,移动到下一个结点 
    }
    return 0;
}

题目二结果展示:

 

2)请分析你程序中每个功能模块的算法时间复杂度。

题目一:

构建含有n个元素的循环链表。时间复杂度为O(n)

本段代码由两层循环构成。内层循环通过从head结点开始报数,报到第m-1个结点,此时寻找到第m个结点(利用第m-1个结点的后继结点)并删除。外层循环在每剔除一个结点后再一次进行遍历。时间复杂度为O(n²)

题目二:

构建含有n个元素的循环链表,a为安全洞的标记,b为洞的序号。时间复杂度为O(n)

本段代码由两层循环构成。内层循环通过题目所给的狐狸进洞的规律,对其所有进入过的洞进行标记(即a=1),便于后续锁定兔子安全洞的位置。外层循环为题目所给的狐狸进洞的总次数(即100次进洞寻找兔子),并继承上一次进洞的位置。时间复杂度为O(n²)

通过之前化简进洞的序号,本段代码利用遍历输出安全洞的位置,即通过从开始的结点中遍历,寻找a标记为0的结点序号并输出。时间复杂度为O(n)


 其他参考:

#include<iostream>
using namespace std;

// 定义结构体 
struct CLNode  
{
	int num;
	CLNode *next;
};
// 初始化链表 
void Initlist(CLNode *&L){  //注意引用!!! 
	L=new CLNode;
	L->next=L;
}
// 创建链表元素
void Creatlist(CLNode *&L,int n){
	CLNode *p=L;
	for(int i=1;i<=n;i++){
		CLNode *q=new CLNode;
		q->num=i;
		q->next=L;   //循环链表的指针指向 
		p->next=q;
		p=q;
	}
}
// 输出链表元素
void Outlist(CLNode *&L){
	CLNode *p=L;
	cout<<"输出小孩序号如下:"<<endl; 
	while(p->next!=L){
		p=p->next;
		cout<<p->num<<" ";
	}
	cout<<endl; 
}
// 输出出列序列
void Output(CLNode *&L,int m){
	CLNode *p=L->next;
	CLNode *pre=L;//定义pre指针以便删除元素操作 
	for(int i=1;i<=m;){
		if(p->next==L){
			if(p->next->next==L)//循环结束条件 
			break;
			else{
				pre=pre->next->next;
				p=p->next->next;
			}
		}
		else{
			pre=pre->next;
			p=p->next;
		}
		i++;
		if(i==m){
			cout<<p->num<<" ";
			pre->next=p->next;
			CLNode *q=p;
			p=p->next;
			q->next=NULL;
			delete q;
			if(p!=L) //注意条件! 
			i=1;
			else
			i=0;  //注意避开头结点 
		}
	}
}
// 释放空间 
void Destroylist(CLNode *&L){
	 delete L;//删除头结点 
}

int main(){
	CLNode *L;       //定义头指针 
	Initlist(L);     //初始化链表 
	
	int n,m;
	cout<<"请输入小孩的总人数:"<<endl;
	cin>>n; 
	Creatlist(L,n);  //插入链表元素 
	
	Outlist(L);      //输出链表元素 
	
	cout<<"请输出出列序号:"<<endl;
	cin>>m;
	cout<<"当n="<<n<<",m="<<m<<"时的出列序号为:"<<endl;
	Output(L,m);    //根据序号输出依次链表元素 
	Destroylist(L);//释放空间 
}
#include<iostream>
using namespace std;
// 定义结构体
struct CLNode  
{
	int num;
	CLNode *next;
};
// 初始化链表
void Initlist(CLNode *&L){  //注意引用!!! 
	L=new CLNode;
	L->next=L;
}
// 创建链表元素
void Creatlist(CLNode *&L,int n){
	CLNode *p=L;
	for(int i=1;i<=n;i++){
		CLNode *q=new CLNode;
		q->num=i;
		q->next=L;   //循环链表的指针指向 
		p->next=q;
		p=q;
	}
}
// 输出链表元素 
void Outlist(CLNode *&L){
	CLNode *p=L;
	cout<<"输出山洞序号如下:"<<endl; 
	while(p->next!=L){
		p=p->next;
		cout<<p->num<<" ";
	}
	cout<<endl; 
}
// 寻找安全洞 
void Safenum(CLNode *&L){
	cout<<"安全洞的编号可能为:"<<endl;
	CLNode *p=L;
	int a[101];    //储存被循环到的链表元素 
	int i=1;
	while(i<=100){   //使循环次数足够多 
		for(int j=0;j<i;j++){
			if(p->next==L)
			p=p->next->next;
			else
			p=p->next;
		}
		a[i-1]=p->num;
		i++;
	}
	for(int j=1;j<=10;j++){
		for(i=0;i<100;i++){
	    	if(a[i]==j)
	    	break;
    	} 
    	if(i>=100)
    	cout<<j<<" ";
	}
}
// 释放空间
void Destroylist(CLNode *&L){
	CLNode *p=L->next;
	while(p!=L){ //除了头结点的所有结点 
		CLNode *q=p;
		p=p->next;
		q->next=NULL;
		delete q;
	}
	 delete p;//删除头结点 
}

int main(){
	CLNode *L;       //定义头指针 
	Initlist(L);     //初始化链表 

	Creatlist(L,10);  //插入链表元素 
	
	Outlist(L);      //输出链表元素 
	
	Safenum(L);    //找到安全洞 
	Destroylist(L);//释放空间 
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/47343.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【项目开发】商城 - 三级分类 - 简单笔记

目录标题 后端业务类实体类 前端最终实现效果排序变化批量删除 后端 业务类 // 省略其他简单的CRUDOverridepublic List<CategoryEntity> listWithTree() {// 1、查出所有分类List<CategoryEntity> list baseMapper.selectList(null);// 2. 找出所有的一级分类Li…

数据库监控工具-PIGOSS BSM

PIGOSS BSM 运维监控系统的重要功能之一是数据库监控&#xff0c;它能够帮助数据库管理员(DBA)和系统管理员监控包含Oracle、SQL Server、MySQL、DB2、PostgreSql、MongoDB、达梦、南大通用、人大金仓、神州通用等多种类异构型的数据库环境。PIGOSS BSM通过执行数据库查询来采集…

【Spring Cloud Alibaba】限流--Sentinel

文章目录 概述一、Sentinel 是啥&#xff1f;二、Sentinel 的生态环境三、Sentinel 核心概念3.1、资源3.2、规则 四、Sentinel 限流4.1、单机限流4.1.1、引入依赖4.1.2、定义限流规则4.1.3、定义限流资源4.1.4、运行结果 4.2、控制台限流4.2.1、客户端接入控制台4.2.2、引入依赖…

基于深度学习的CCPD车牌检测系统(PyTorch+Pyside6+YOLOv5模型)

摘要&#xff1a;基于CCPD数据集的高精度车牌检测系统可用于日常生活中检测与定位车牌目标&#xff0c;利用深度学习算法可实现图片、视频、摄像头等方式的车牌目标检测识别&#xff0c;另外支持结果可视化与图片或视频检测结果的导出。本系统采用YOLOv5目标检测模型训练数据集…

【Spring篇】初识 Spring IoC 与 DI

目录 一. Spring 是什么 ? 二. 何为 IoC ? 三. 如何理解 Spring IoC ? 四. IoC 与 DI 五 . 总结 一. Spring 是什么 ? 我们通常所说的 Spring 指的是 Spring Framework&#xff08;Spring 框架&#xff09;&#xff0c;它是⼀个开源框架&#xff0c;有着活跃⽽ 庞⼤…

逻辑回归概述

逻辑回归介绍 1. 逻辑回归的应用场景 逻辑回归(Logistic Regression)是机器学习中的 一种分类模型 ,逻辑回归是一种分类算法,虽然名字中带有回归。由于算法的简单和高效,在实际中应用非常广泛 广告点击率是否为垃圾邮件是否患病信用卡账单是否会违约 逻辑回归就是解决二…

day14 | 100.二叉树的最大深度 111.二叉树的最小深度 222.完全二叉树的节点个数

文章目录 一、二叉树的最大深度二、二叉树的最小深度三、完全二叉树的节点数 一、二叉树的最大深度 100.二叉树的最大深度 因为题给出的高度和深度是一样的&#xff0c;所以求得结果都能过。 class Solution { public:int getHeight(TreeNode *node){if (node nullptr)retu…

Pytest学习教程_基础知识(一)

前言 pytest是一个用于编写和执行Python单元测试的框架。它提供了丰富的功能和灵活性&#xff0c;使得编写和运行测试变得简单而高效。 pytest的一些主要特点和解释如下&#xff1a; 自动发现测试&#xff1a;pytest会自动查找以"test_"开头的文件、类和函数&#x…

腾讯 SpringBoot 高阶笔记,限时开源 48 小时,真香警告

众所周知&#xff0c;SpringBoot 最大的一个优势就是可以进行自动化配置&#xff0c;简化配置&#xff0c;不需要编写太多的 xml 配置文件&#xff1b;基于 Spring 构建&#xff0c;使开发者快速入门&#xff0c;门槛很低&#xff1b;SpringBoot 可以创建独立运行的应用而不需要…

【学习笔记】目标跟踪领域SOTA方法比较

目录 前言方法1 TraDeS:2 FairMOT:3 SMILEtrack:4 ByteTrack: 前言 常用于行人跟踪的多目标跟踪数据集包括&#xff1a;MOT 15/16/17/20、PersonPath22等… 为更好比较现有SOTA算法的检测性能&#xff0c;本博客将针对在各数据集上表现较优的算法模型进行介绍。&#xff08;表…

ip校园广播音柱特点

ip校园广播音柱特点IP校园广播音柱是一种基于IP网络技术的音频播放设备&#xff0c;广泛应用于校园、商业区、公共场所等地方。它可以通过网络将音频信号传输到不同的音柱设备&#xff0c;实现远程控制和集中管理。IP校园广播音柱具备以下特点和功能&#xff1a;1. 网络传输&am…

SSM框架 基础

1.数据库 2.工程 3.pom 4.web.xml 5.spring配置文件头部 6.实体类 7.StudentMapper接口 8. StudentMapper.xml 9.StudentService 10. StudentServiceImpl 11.StudentController 实战 查询所有 StudentMapper StudentService StudentServiceImpl StudentMapper.xml Stude…

效率与质量兼备的6个设计工具!

今天本文为大家推荐的这6个设计工具&#xff0c;将帮助设计师实现高效工作&#xff0c;同时也更好地展示自己的创作力&#xff0c;一起来看看吧&#xff01; 1、即时设计 即时设计是一款国内的设计工具&#xff0c;它为设计师提供了非常多实用的设计功能和精致的设计素材&…

TCP状态转换图

TCP状态转换图 了解TCP状态转换图可以帮助开发人员查找问题. 说明: 上图中粗线表示主动方, 虚线表示被动方, 细线部分表示一些特殊情况, 了解即可, 不必深入研究. 对于建立连接的过程客户端属于主动方, 服务端属于被动接受方(图的上半部分) 而对于关闭(图的下半部分), 服务端…

day41-Verify Account Ui(短信验证码小格子输入效果)

50 天学习 50 个项目 - HTMLCSS and JavaScript day41-Verify Account Ui&#xff08;短信验证码小格子输入效果&#xff09; 效果 index.html <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8" /><meta name&qu…

【西安交通大学】:融合传统与创新的学府之旅

【西安交通大学】&#xff1a;融合传统与创新的学府之旅 引言历史与发展学校特色学科优势院系专业校园环境与设施学生生活与社团活动校友荣誉与成就未来发展展望总结&#x1f340;小结&#x1f340; &#x1f389;博客主页&#xff1a;小智_x0___0x_ &#x1f389;欢迎关注&…

Linux基础以及常用命令

目录 1 Linux简介1.1 不同应用领域的主流操作系统1.2 Linux系统版本1.3 Linux安装1.3.1 安装VMWare1.3.2 安装CentOS镜像1.3.3 网卡设置1.3.4 安装SSH连接工具1.3.5 Linux和Windows目录结构对比 2 Linux常用命令2.0 常用命令&#xff08;ls&#xff0c;pwd&#xff0c;cd&#…

你说你会Java手动锁,但你会这道题吗???

按照这个格式输出你会吗&#xff1f;&#xff1f;&#xff1f; 你说你不会&#xff0c;接下来认真看认真学了。 1.首先引入原子类。AtomicInteger num new AtomicInteger(0); 什么是原子类&#xff1f; 就是可以保证线程安全的原子操作的数据类型。 有什么作用&#xff1f;…

2.2 模型与材质基础

一、渲染管线与模型基础 1. 渲染管线 可编程阶段&#xff08;蓝色区域&#xff09;&#xff1a; 1顶点着色器 2几何着色器 3片元着色器 2. 模型的实现原理 UV&#xff1a;在建模软件中&#xff0c;进行UV展开&#xff0c;UV会放在一个横向为U纵向为V&#xff0c;范围&#xff0…

【Linux】深入理解缓冲区

目录 什么是缓冲区 为什么要有缓冲区 缓冲区刷新策略 缓冲区在哪里 手动设计一个用户层缓冲区 什么是缓冲区 缓冲区本质上一块内存区域&#xff0c;用来保存临时数据。缓冲区在各种计算任务中都广泛应用&#xff0c;包括输入/输出操作、网络通信、图像处理、音频处理等。 …