数据结构--循环链表

news2025/7/11 9:45:35

目录

1.为什么要有循环链表

2.定义

3.循环链表和单链表的图示对比

4.循环链表和单链表的代码对比

5.循环链表的操作

1.clist.h

2.clist.cpp

1.初始化plist

2.往plist中头部插入数字val

3.往plist中的尾部插入数字val

4.在plist中查找val值,找到返回该节点地址,失败返回NULL

5.删除plist中的第一个val

6.判断plist是否为空链表(没有数据节点)

7.获取plist长度,数据节点的个数

8.获取plist链表的pos位置的值

9.获取val的前驱

10.获取val的后继

11.输出plist的所有数据


1.为什么要有循环链表

在单链表中我们是把结点遍历一遍后就结束了,为了使表处理更加方便灵活,我们希望通过任意一个结点出发都可以找到链表中的其它结点,因此我们引入了循环链表。

2.定义

将单链表中终端结点的指针端由空指针改为头结点,就使整个单链表形成了一个环,这种头尾相接的单链表称为循环链表。

简单理解就是形成一个闭合的环,在环内寻找自己需要的结点。

3.循环链表和单链表的图示对比

单链表:

 循环链表:

4.循环链表和单链表的代码对比

单链表:

typedef struct Node{ //定义单链表结点类型
	int data; //数据域,可以是别的各种数据类型
	struct Node *next; //指针域
}LNode, *LinkList;

循环链表:

typedef struct CNode//循环链表节点
{
	ElemType data;//数据
	struct CNode* next;//后继指针
}CNode ,*CList;

5.循环链表的操作

//带头结点的循环链表,其尾节点的后继为头结点(不是NULL)
//节点的结构和单链表一样

1.clist.h

#pragma once

typedef int ElemType;

typedef struct CNode//循环链表节点
{
	ElemType data;//数据
	struct CNode* next;//后继指针
}CNode ,*CList;

//初始化plist
void InitList(CList plist);

//往plist中头部插入数字val
bool Insert_head(CList plist, ElemType val);

//往plist中的尾部插入数字val
bool Insert_tail(CList plist, ElemType val);

//在plist中查找val值,找到返回该节点地址,失败返回NULL
CNode* Search(CList plist, ElemType val);

//删除plist中的第一个val
bool DeleteVal(CList plist, ElemType val);

//判断plist是否为空链表(没有数据节点)
bool IsEmpty(CList plist);

//获取plist长度,数据节点的个数
int GetLength(CList plist);

//获取plist链表的pos位置的值
bool GetElem(CList plist, int pos, int* rtval);//rtval:输出参数

//获取val的前驱
CNode* Prior(CList plist, ElemType val);

//获取val的后继
CNode* Next(CList plist, ElemType val);

//输出plist的所有数据
void Show(CList plist);

//清空数据
void Clear(CList plist);

//销毁
void Destroy(CList plist);

2.clist.cpp

1.初始化plist

oid InitList(CList plist)
{
	assert(plist != NULL);
	if (plist == NULL)
		return;
	//数据域不使用
	plist->next = plist;
}

2.往plist中头部插入数字val

这里我们需要思考一下当链表为空时是否适用:这里明确告诉大家不管是否是空链表,这两行代码均可以使用,下面给大家用示意图表示一下;
不是空链:

 是空链:

 

bool Insert_head(CList plist, ElemType val)
{
	//1.动态申请一个新的节点
	CNode* p = (CNode*)malloc(sizeof(CNode));
	assert(p != NULL);
	if (p == NULL)
		return false;
	//2.把数据存放在新节点中
	p->data = val;

	//3.把新节点插入在头结点后面
	p->next = plist->next;
	plist->next = p;

	return true;
}

3.往plist中的尾部插入数字val

bool Insert_tail(CList plist, ElemType val)
{
	//1.创建新节点并赋值
	CNode* p = (CNode*)malloc(sizeof(CNode));
	assert(p != NULL);
	if (p == NULL)
		return false;
	p->data = val;

	//2.找到尾节点
	CNode* q;
	for (q = plist; q->next != plist; q = q->next)
		;
		
	//3.插入新节点.把p插入在q的后面
	p->next = q->next;
	q->next = p;

	return true;
}

与单向链表的插入不同,循环单链表插入时只能往表头节点的后面插入,由初始结构可知,想完成插入操作,必须先找到要插入位置的前一个节点,然后修改相应指针即可完成操作。

 

 

4.在plist中查找val值,找到返回该节点地址,失败返回NULL

CNode* Search(CList plist, ElemType val)
{
	for (CNode* p = plist->next; p != plist; p = p->next)
	{
		if (p->data == val)
			return p;
	}
	return NULL;
}

5.删除plist中的第一个val

bool DeleteVal(CList plist, ElemType val)
{
	CNode* p = Prior(plist, val);
	if (p == NULL)
		return false;
	CNode* q = p->next;//保存需要删除的节点
	p->next = q->next;//剔除q
	free(q);//释放节点

	return true;
}

6.判断plist是否为空链表(没有数据节点)

bool IsEmpty(CList plist)
{
	return plist->next == plist;
}

7.获取plist长度,数据节点的个数

int GetLength(CList plist)
{
	int count = 0;//计数器
	for (CNode* p = plist->next; p != plist; p = p->next)
		count++;

	return count;
}

8.获取plist链表的pos位置的值

bool GetElem(CList plist, int pos, int* rtval)//rtval:输出参数
{
	if (pos < 0 || pos >= GetLength(plist))
		return false;

	CNode* p = plist->next;
	for (int i = 0; i < pos; i++)
	{
		p = p->next;
	}

	*rtval = p->data;
	return true;
}

9.获取val的前驱

CNode* Prior(CList plist, ElemType val)
{
	for (CNode* p = plist; p->next != plist; p = p->next)
	{
		if (p->next->data == val)
			return p;
	}
	return NULL;
}

10.获取val的后继

CNode* Next(CList plist, ElemType val)
{
	CNode* p = Search(plist,val);
	if (p == NULL)
		return NULL;

	return p->next;
}

11.输出plist的所有数据

void Show(CList plist)
{
	//从头到尾遍历数据节点
	for (CNode* p = plist->next; p != plist; p = p->next)
	{
		printf("%d ",p->data);
	}
	printf("\n");
}

#include <stdio.h>
#include "clist.h"
//#include <vld.h>//需要安装vld

int main()
{
	CNode head;//循环链表的表头节点
	InitList(&head);
	
	for (int i = 0; i < 10; i++)
	{
		Insert_head(&head,i);//9 8 7 6 5 4 3 2 1 0
		Insert_tail(&head,i);//0,1,2,3,4,5,6,7,8,9
	}
	Show(&head);
	CNode* p;
	for (int i = -1; i < 12; i++)
	{
		if ((p = Search(&head, i)) != NULL)
		{
			printf("%d找到了\n",i);
		}
		else
		{
			printf("%d没有找到\n",i);
		}
	}

	//for (int i = -1; i < 11; i++)
	//{
	//	DeleteVal(&head,i);
	//}

	int val;
	GetElem(&head,3,&val);
	printf("%d\n",val);

	Show(&head);
	Destroy(&head);
	//Destroy(&head);

	return 0;
}

 

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

SpringAOP(2)-spring源码详解(七)

上篇文章说了spring的aop&#xff0c;在启动类加一个启动注解&#xff0c;注解点进源码可以看到注册了bean定义的后置处理器。每个切入点都会生成一个adviosr&#xff0c;他们会排序好依次注册。 他的顺序是before、after、afterRturning、afterThrowing 原创 SpringAOP&…

Mac解决鼠标滚轮反方向移动逻辑--Mos(又免费又好用哦~)

目录&#xff1a;&#x1f335;&#x1f335;&#x1f335;前言什么&#xff1f;Mac竟然需要鼠标&#xff1f;Mos &#xff0c;让你的鼠标丝般顺滑&#xff5e;❤️❤️❤️忙碌的敲代码也不要忘了浪漫鸭&#xff01;&#x1f335;&#x1f335;&#x1f335;前言 ✨你好啊&…

PHP连接外部服务器的MySQL参考教程

PHP连接AWS服务器 云服务器上安装MySQL参考教程 linux-安装MySQL&#xff1a;https://blog.csdn.net/xhmico/article/details/125197747云端服务器(linux版)部署mysql&#xff1a;https://blog.csdn.net/m0_51406695/article/details/123886966linux云服务器从零开始安装mysq…

你不能错过的【Python爬虫】测试2(完整源代码+架构+结果)

目录 一、关键工具包的环境以及版本二、架构展示三、各部分code3.1 yjs.py3.2 items.py3.3 middlewares.py3.4 pipelines.py3.5 settings.py四、结果4.1 控制台输出结果4.2 结果截图一、关键工具包的环境以及版本 scrapy:2.7.1版本(这里主要用到的工具包) 二、架构展示 三…

HyperLynx(三十二)高速串行总线仿真(四)

高速串行总线仿真&#xff08;四&#xff09; 在上节的基础上 1.通过导出到LineSim验证一个串行通道 2.快速眼图仿真 1.通过导出到LineSim验证一个串行通道 接下来&#xff0c;将导出网络到LineSim&#xff0c;并为电容分配SPICE模型。然后&#xff0c;将添加封装和串行电容…

WENO格式自动推导

简介 WENO格式是CFD中的一种高精度的数值格式。如果函数光滑&#xff0c;使用rrr个模板可以在空间上达到2r−12r-12r−1。如果出现间断&#xff0c;那么WENO格式退化为ENO格式。 理论上WENO可达任意阶精度&#xff0c;但是推导过程比较繁琐。本文使用Mathematica软件完成WENO…

一个简单的HTML网页(千与千寻电影) 大二学生网页设计与制作 电影主题网页制作

HTML实例网页代码, 本实例适合于初学HTML的同学。该实例里面有设置了css的样式设置&#xff0c;有div的样式格局&#xff0c;这个实例比较全面&#xff0c;有助于同学的学习,本文将介绍如何通过从头开始设计个人网站并将其转换为代码的过程来实践设计。 文章目录一、网页介绍一…

C++ 多态之虚函数表

虚函数表概述 C 的多态&#xff0c;使用动态绑定的技术,技术的核心是虚函数表&#xff08;简称虚表&#xff09;&#xff0c;每个包含了虚函数的类都包含一个虚表&#xff0c;虚表是属于类的&#xff0c;而不是属于某个具体的对象&#xff0c;一个类只需要一个虚表即可。同一个…

猴子也能学会的jQuery第十期——jQuery元素操作(下)

&#x1f4da;系列文章—目录&#x1f525; 猴子也能学会的jQuery第一期——什么是jQuery 猴子也能学会的jQuery第二期——引用jQuery 猴子也能学会的jQuery第三期——使用jQuery 猴子也能学会的jQuery第四期——jQuery选择器大全 猴子也能学会的jQuery第五期——jQuery样式操作…

树莓派系统安装,使用SSD/U盘启动centos

树莓派系统安装&#xff0c;使用SSD/U盘启动centos argon m2 外壳厂家资料 https://www.waveshare.net/wiki/PI4-CASE-ARGON-ONE-M.2 TF卡安装系统 如果是使用TF卡安装&#xff0c;则参考官方文档按步骤安装即可&#xff1a; https://www.waveshare.net/wiki/Raspberry_Pi_Do…

FAlphaBlend——Unreal中的插值助手

游戏开发中经常要进行插值处理&#xff0c;这个东西处理虽然不复杂&#xff0c;但如果自己重新做&#xff0c;还是要写额外的代码&#xff0c;好消息是&#xff0c;Unreal已经为我们提供了插值助手——FAlphaBlend。 我们以一个非常简单的应用场景来说明FAlphaBlend的用处&…

matplotlib详细教学

Matplotlib初相识 认识matplotlib Matplotlib是一个Python 2D绘图库&#xff0c;能够以多种硬拷贝格式和跨平台的交互式环境生成出版物质量的图形&#xff0c;用来绘制各种静态&#xff0c;动态&#xff0c;交互式的图表 一个最简单的绘图例子 matplotlib的图像都是画在对应…

Spring事务与事务传播机制

目录 1.事务的基本概念 2.Spring事务的实现 3.事务隔离级别 4.事务传播机制 1.事务的基本概念 关于事务的一些基础概念我已经在MYSQL中讲解过了&#xff0c;有不了解的可以移步至此篇文章&#xff1a;MySQL基础——数据库索引与事务_invictusQAQ的博客-CSDN博客 2.Spring…

基于AlexNet卷积神经网络的手写体数字倾斜校正系统研究-附Matlab代码

⭕⭕ 目 录 ⭕⭕✳️ 一、引言✳️ 二、AlexNet 网络✳️ 三、实验验证✳️ 3.1 实验数据集✳️ 3.2 数据训练✳️ 3.3 手写体倾斜数字校正结果✳️ 四、参考文献✳️ 五、Matlab代码获取✳️ 一、引言 手写体数字识别是光学字符识别(Optical Character&#xff32;ecognition…

破圈的《张朝阳的物理课》,开启“知识突围”的搜狐视频

在互联网耕耘二十多年的搜狐&#xff0c;正在焕发出新的活力。 从搜狐最近公布的2022年第三季度财报来看&#xff0c;营收1.85亿美元&#xff0c;其中在线游戏业务实现收入1.49亿美元&#xff0c;广告收入环比增长3%达到2600万美元。同时&#xff0c;净亏损好于此前预期。 对…

Junit执行源码分析,junit是怎么跑起来的(二)

接上一篇【Junit执行源码分析&#xff0c;junit是怎么跑起来的】 https://blog.csdn.net/Aqu415/article/details/127494898 这里我们接着分析 org.junit.runner.JUnitCore#run(org.junit.runner.Runner) 这个方法 public Result run(Runner runner) {Result result new Resu…

智慧监狱解决方案-最新全套文件

智慧监狱解决方案-最新全套文件一、建设背景二、思路架构三、建设方案四、获取 - 智慧监狱全套最新解决方案合集一、建设背景 “智慧监狱”是“数字法治、智慧司法”信息系统建设的重要组成部分&#xff0c;其主要内容是在现有监狱信息建设的基础上&#xff0c;充分利用大数据…

【机器学习】拉格朗日对偶性

有任何的书写错误、排版错误、概念错误等&#xff0c;希望大家包含指正。 拉格朗日对偶性 在求解最优化问题中&#xff0c;拉格朗日乘数法&#xff08;Lagrange Multiplier&#xff09;和 KKT&#xff08;Karush Kuhn Tucker&#xff0c;三个人名&#xff09;条件是两种最常用…

高性能零售IT系统的建设07-通过一次重大危机感受Redis从使用到失智到理性的治理

介绍 在2020年年初我接手的一座“屎山”里含有Redis框架和机制&#xff0c;它使用的是sentinel模式。其实sentinel模式并不是重点&#xff0c;按照我的经验&#xff0c;每天单店10万单也一样可以使用Redis Sentinel。只有到达新浪微博啦、头条啦这种大厂才有必要去架设redis cl…

Linux进程替换

进程替换 假如操作系统正在执行某一个程序&#xff0c;我们可以利用程序替换函数指定一个新的程序&#xff0c;让操作系统去执行我们新指定的程序。也就是这样一种情形下&#xff0c;我们fork一个进程&#xff0c;如果fork成功&#xff0c;子进程会和父进程执行相同的代码&…