数据结构:双向循环链表的实现

数据机构C语言用双向循环链表实现通讯簿 1 课程设计介绍 1 1.1 课程设计内容 1 1.2 课程设计要求 1 2 课程设计原理 2 2.1 课设题目粗略分析 2 2.2.2 流程图分析 3 3.1 存储结构 6 3.2 算法描述 6 4.1 调试过程 10 参考文献 12 附 录(关键部分程序清单) 13 1.1 课程设计内容 利用双向循环链表作为储存结构设计并实现一个通讯录程序。可以实现信息的添加、插入、删除、查询和统计等功能 1.2 课程设计要求 (1) 每条信息至少包含:姓名(name)、街道(street)、城市(city)、邮编、(eip)、国家(state)几项; (2) 作为一个完整的系统。应该具有有好的界面和较强的容错能力。 立即下载

以下代码为双向循环链表的实现,在vc++ 6.0 和 Dev-C++ 下编译通过。代码总体上来自于严蔚敏老师的数据结构教材,做了少量修改。

#include<stdio.h>
#include<stdlib.h>
#include<math.h>
 
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define INFEASIBLE -1
 
typedef int Status;
typedef int Boolean;
typedef int ElemType;

typedef struct DuLNode
{
	ElemType data;
	struct DuLNode *prior,*next;
}DuLNode,*DuLinkList;

Status InitList(DuLinkList &L)
{	/* 产生空的双向循环链表L */
	L=(DuLinkList)malloc(sizeof(DuLNode));
	if(L)
	{
		L->next=L->prior=L;
		return OK;
	}
	else
		return OVERFLOW;
}

Status DestroyList(DuLinkList &L)
{ /*销毁双向循环链表L */
	DuLinkList q,p=L->next; /* p指向第一个结点 */
	while(p!=L) /* p没到表头 */
	{
		q=p->next;
		free(p);
		p=q;
	}
	free(L);
	L=NULL;
	return OK;
}

Status ClearList(DuLinkList L) /* 不改变L */
{	/* 初始条件:L已存在。操作结果:将L重置为空表 */
	DuLinkList q,p=L->next; /* p指向第一个结点 */
	while(p!=L) /* p没到表头 */
	{
		q=p->next;
		free(p);
		p=q;
	}
	
	L->next=L->prior=L; /* 头结点的两个指针域均指向自身 */
	return OK;
}

Status ListEmpty(DuLinkList L)
{ /* 初始条件:线性表L已存在。操作结果:若L为空表,则返回TRUE,否则返回FALSE */
	if(L->next==L&&L->prior==L)
		return TRUE;
	else
		return FALSE;
}

int ListLength(DuLinkList L)
{ /* 初始条件:L已存在。操作结果:返回L中数据元素个数 */
	int i=0;
	DuLinkList p=L->next; /* p指向第一个结点 */
	while(p!=L) /* p没到表头 */
	{
		i++;
		p=p->next;
	}
	return i;
}

Status GetElem(DuLinkList L,int i,ElemType &e)
{ /* 当第i个元素存在时,其值赋给e并返回OK,否则返回ERROR */
	int j=1; /* j为计数器 */
	DuLinkList p=L->next; /* p指向第一个结点 */
	while(p!=L&&j<i) /* 顺指针向后查找,直到p指向第i个元素或p指向头结点 */
	{
		p=p->next;
		j++;
	}
	if(p==L||j>i) /* 第i个元素不存在 */
		return ERROR;
	e=p->data; /* 取第i个元素 */
	return OK;
}

int LocateElem(DuLinkList L,ElemType e)
{  /* 初始条件:L已存在*/
   /* 操作结果:返回L中第1个与e相等的数据元素的位序。 */
   /*           若这样的数据元素不存在,则返回值为0 */
	int i=0;
	DuLinkList p=L->next; /* p指向第1个元素 */
	while(p!=L)
	{
		i++;
		if(p->data==e) /* 找到这样的数据元素 */
		return i;
		p=p->next;
	}
	return 0;
}

Status PriorElem(DuLinkList L,ElemType cur_e,ElemType &pre_e)
{  /* 操作结果:若cur_e是L的数据元素,且不是第一个,则用pre_e返回它的前驱, */
   /*           否则操作失败,pre_e无定义 */
	DuLinkList p=L->next->next; /* p指向第2个元素 */
	while(p!=L) /* p没到表头 */
	{
		if(p->data==cur_e)
		{
			pre_e=p->prior->data;
			return TRUE;
		}
		p=p->next;
	}
	return FALSE;
}

Status NextElem(DuLinkList L,ElemType cur_e,ElemType &next_e)
{ /* 操作结果:若cur_e是L的数据元素,且不是最后一个,则用next_e返回它的后继, */
   /*           否则操作失败,next_e无定义 */
	DuLinkList p=L->next->next; /* p指向第2个元素 */
	while(p!=L) /* p没到表头 */
	{
		if(p->prior->data==cur_e)
		{
			next_e=p->data;
			return TRUE;
		}
		p=p->next;
	}
	return FALSE;
}

DuLinkList GetElemP(DuLinkList L,int i) /* 另加 */
{ /* 在双向链表L中返回第i个元素的位置指针*/
	int j;
	DuLinkList p=L;
	if(i<1 || i>ListLength(L))
		return L;
	for(j=1;j<=i;j++)
		p=p->next;
	return p;
}

Status ListInsert(DuLinkList L,int i,ElemType e) 
{ /* 在带头结点的双链循环线性表L中第i个位置之前插入元素e,i的合法值为1≤i≤表长+1 */
	DuLinkList p,s;
	if(i<1||i>ListLength(L)+1) /* i值不合法 */
		return ERROR;
	p=GetElemP(L,i-1); /* 在L中确定第i-1个元素的位置指针p */
	s=(DuLinkList)malloc(sizeof(DuLNode));
	if(!s)
		return OVERFLOW;
	s->data=e; /* 在第i-1个元素之后插入 */
	s->prior=p;
	s->next=p->next;
	p->next->prior=s;
	p->next=s;
	return OK;
}

Status ListDelete(DuLinkList L,int i,ElemType &e)
{ /* 删除带头结点的双链循环线性表L的第i个元素,i的合法值为1≤i≤表长+1 */
	DuLinkList p;
	if(i<1||i>ListLength(L)) /* i值不合法 */
		return ERROR;
	p=GetElemP(L,i);  /* 在L中确定第i个元素的位置指针p */
	e=p->data;
	p->prior->next=p->next;
	p->next->prior=p->prior;
	free(p);
	return OK;
}

void ListTraverse(DuLinkList L)
{ /* 由双链循环线性表L的头结点出发,打印输出各个结点的数据,printf("%d ",p->data)可以根据需要替换为其他语句 */
	DuLinkList p=L->next; /* p指向头结点 */
	while(p!=L)
	{
		printf("%d ",p->data);
		p=p->next;
	}
	printf("\n");
}

void ListTraverseBack(DuLinkList L)
{ /* 由双链循环线性表L的头结点出发,逆序打印输出各个结点的数据,printf("%d ",p->data)可以根据需要替换为其他语句*/
	DuLinkList p=L->prior; /* p指向尾结点 */
	while(p!=L)
	{
		printf("%d ",p->data);
		p=p->prior;
	}
	printf("\n");
}

void main()
{
	DuLinkList L;
	int i,n;
   	Status j;
   	ElemType e;
   	InitList(L);
   	for(i=1;i<=5;i++)
     	ListInsert(L,i,i); /* 在第i个结点之前插入i */
   	printf("正序输出链表:");
   	ListTraverse(L); /* 正序输出 */
   	printf("逆序输出链表:");
   	ListTraverseBack(L); /* 逆序输出 */
   	n=2;
   	ListDelete(L,n,e); /* 删除并释放第n个结点 */
   	printf("删除第%d个结点,值为%d,其余结点为:",n,e);
   	ListTraverse(L); /* 正序输出 */
   	printf("链表的元素个数为%d\n",ListLength(L));
   	printf("链表是否空:%d(1:是 0:否)\n",ListEmpty(L));
   	ClearList(L); /* 清空链表 */
   	printf("清空后,链表是否空:%d(1:是 0:否)\n",ListEmpty(L));
   	for(i=1;i<=5;i++)
    	ListInsert(L,i,i); /* 重新插入5个结点 */
   	ListTraverse(L); /* 正序输出 */
   	n=3;
   	j=GetElem(L,n,e); /* 将链表的第n个元素赋值给e */
   	if(j)
     	printf("链表的第%d个元素值为%d\n",n,e);
   	else
     	printf("不存在第%d个元素\n",n);
   	n=4;
   	i=LocateElem(L,n);
   	if(i)
     	printf("等于%d的元素是第%d个\n",n,i);
   	else
     	printf("没有等于%d的元素\n",n);
   	j=PriorElem(L,n,e);
   	if(j)
     	printf("%d的前驱是%d\n",n,e);
   	else
     	printf("不存在%d的前驱\n",n);
   	j=NextElem(L,n,e);
   	if(j)
     	printf("%d的后继是%d\n",n,e);
   	else
     	printf("不存在%d的后继\n",n);
   	DestroyList(L);
}

 

数据结构--双向循环链表实践 c语言实现:利用双向循环链表,用户输入一个数使得26个字母的排列发生变化,例如用户输入3,输出结果:DEFGHIJKLMNOPQRSTUVWXYZABC 立即下载

相关推荐

SAP CKMLCP 月结7大常见报错:从“未找到成本核算运行”到“物料占用”的完整解决方案

本文深入解析SAP CKMLCP月结过程中的7大常见报错,从权限问题到数据一致性错误,提供系统化的解决方案。重点解决'未找到成本核算运行'和'物料占用'等典型问题,帮助财务人员高效完成成本核算月结,确保数据准确性。

weixin_30299709的博客 415

数据结构——“双向循环链表“ 易懂刨析双向循环链表(图解+代码)

循环链表单向循环链表双向循环链表1. 双向循环链表——插入2. 双向循环链表——删除 单向循环链表 关于两个循环链表合并为一个循环链表 双向循环链表 在单链表L中,查找ai的后继Next(L,a;),耗时仅为O(1),因为取ai后继指针即可。 但查找a;的直接前驱Prior(L,ai);则需从链表的头指针开始,找到结点ai前一结点即是。故运算Prior(L,ai)依赖表长n,耗时为O(n)。另外,若链表中有一指针值被破坏,则整个链表脱节。这是单链表的不足 为此,引入双向链表。先定义双向链表中的结点:

weixin_44278698的博客 2万+

手把手教你搭建Howland电流源:从原理图到实测避坑指南(附Python数据分析)

本文详细介绍了Howland电流源的设计与实现,从原理图到实测避坑指南,涵盖电阻匹配、运放选择和PCB布局等关键环节。通过Python数据分析,展示了如何优化电路性能并解决常见问题,适合电子工程师和爱好者参考。

weixin_29291069的博客 632

【C语言数据结构】双向循环链表

目录 前言 一、双向循环链表 循环结构 1.双向循环链表头文件及函数声明 2.初始化 1.结点构造 2.初始化函数 3.结点申请 4.数据插入 1.按位置插入 2.尾插 3.头插 5.查找 6.数据删除 1.按位置删除 2.按值删除 3.尾删 4.头删 7.清空与销毁 1.清空 2.销毁 8.双向循环链表源文件及整体函数实现 总结 前言 这次我们将学习双向循环链表,首先了解双向链表和循环链表的定义和讲解。 双向链表也叫双链...

W1024201的博客 7316

基于Halium 9为小米平板4移植Ubuntu Touch:内核适配与驱动调试实战

在移动设备生态中,Linux内核作为核心,通过硬件抽象层(HAL)管理底层硬件驱动,为上层系统提供统一接口。其模块化设计允许深度定制,是实现跨平台移植的技术基础。Halium项目正是利用这一原理,构建了一个中间层,将安卓内核的硬件支持能力“翻译”成标准Linux发行版能识别的格式,从而在手机、平板等移动设备上运行Ubuntu Touch、postmarketOS等移动Linux系统,极大地拓展了老旧设备的再利用价值。这一技术为开发者提供了在常见安卓硬件上进行Linux系统开发与定制的可能,尤其在嵌入式与物联

weixin_42639246的博客 371

告别Overleaf!本地LaTeX环境配置:VSCode+TeXLive完全指南(Windows/Mac双平台)

本文详细介绍了如何在Windows和Mac平台上配置本地LaTeX环境,使用VSCode和TeXLive打造高效的专业写作工作流。从TeXLive安装到VSCode插件配置,再到高级技巧与性能优化,帮助用户摆脱Overleaf限制,实现更快速、更私密的学术写作体验。

3c4x5z6v7b的博客 952

【数据结构】双向循环链表

双向循环链表的结构体定义 初始化双向循环链表 尾插法构建双向循环链表 双向循环链表的后序遍历操作 主函数调用 目录: 目录: 各部分实现: 双向循环链表的结构体定义 初始化双向循环链表 尾插法构建双向循环链表 双向循环链表的后序遍历操作 主函数调用 全部代码: 各部分实现: 双向循环链表的结构体定义 双向链表的每个结点需要连接前一个结点和后一个结...

zhongyebiao的博客 2万+

RH850从0搭建Autosar开发环境【3X】- Davinci Configurator之Port模块配置详解(MCAL配置)

RH850从0搭建Autosar开发环境【3X】- Davinci Configurator之Port模块配置详解(MCAL配置)

weixin_42412049的博客 2276

数据结构篇三:双向循环链表

;前面我们学习了单链表的实现,我们发现它在进行从后往前查找的时候有很大的不便,为了解决这个问题,双向链表油然而生。它可以很好的解决单链表无法从后往前查找的困难。

忘忧. 2151

【动态导通电阻】p-GaN HEMTs正向和反向导通下的动态导通电阻

2024年,浙江大学的研究团队通过多组双脉冲测试方法,深入研究了两种商用p-GaN栅极HEMTs在正向和反向导通模式下的动态导通电阻(RON)特性。研究发现,肖特基型p-GaN栅极HEMTs在反向导通时动态RON比正向导通高3%-5%,而混合漏极嵌入栅注入晶体管在反向导通时动态RON降级较轻,降低约10%。此外,随着漏极电流(IDS)的增加,两种器件在反向导通时动态RON先减小后增加,形成“谷底”现象。

荷塘阅色 825

杰理AC695N芯片跑iic接口的oled驱动分享

本文介绍了一个基于IIC接口的0.96寸OLED显示屏驱动程序,适用于SSD1306控制器。驱动采用软件模拟IIC方式,支持字符、数字、字符串、汉字和图片显示,测试平台为杰理AC695N系列芯片。硬件参数包括128×64分辨率,IIC接口(地址0x78),使用IO_PORTA_02(SDA)和IO_PORTA_03(SCL)引脚。驱动包含OLED主文件(oled.c/h)、软件IIC实现(soft_iic.c/h)和字体/图片数据文件(oledfont.h/bmp.h),可通过修改soft_iic.h中的引

qq_42014563的博客 882

数据结构——双向循环链表

双向循环链表,在原单链表的基础上多了一个指向上一个结点的前驱指针prev,这样前后结点就不仅仅有了单向的从头至尾的指向顺序,也可以从后指向前,从末结点指向头结点。双向带头循环链表结构} DGR;加入前驱指针后,不管是对于链表数据的尾插尾删,或是头插头删,其时间复杂度都为O(1),大大简化了链表遍历过程,而可以直接在链表首尾增减数据,因为一个链表的末节点可由头结点的前驱指针直接访问而不需要遍历至尾。为了简化文本描述,本章双向循环带头链表均简称为双向链表。...

qq_67611811的博客 2635

OTA 升级失败/回滚策略设计:打造安全可靠的双分区/断点续传/签名校验方案

双分区机制(A/B Partitioning)是OTA升级的“保险箱”。简单来说,设备存储分为两个分区:A分区(当前运行)和B分区(备用)。升级时,新固件写入B分区,A分区保持不变。如果升级成功,系统切换到B分区运行;如果失败,设备直接回滚到A分区,完全不受影响。这就像玩游戏存档:你打Boss前存了个档,万一挂了还能读档重来。双分区就是设备的“读档”机制,避免了变砖的尴尬。以Android设备为例,Google从Android 7.0开始强制引入A/B分区机制(Seamless Updates)。

大模型大数据攻城狮的专栏 1234

数据结构:循环链表、双向链表实现及使用

文章目录一、循环链表1.1循环链表基本概念1.2循环链表基本操作1.3循环链表实现及使用二、双向链表2.1双向链表基本概念2.2双向链表基本操作2.3双向链表实现及使用 一、循环链表 1.1循环链表基本概念 1.2循环链表基本操作 1.3循环链表实现及使用 二、双向链表 2.1双向链表基本概念 2.2双向链表基本操作 2.3双向链表实现及使用 ...

Rain的博客 942

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

数据结构:双向循环链表的实现(附有详细图解)

双向循环链表的实现 (1)动态申请节点 在这里插入代码片

qq_44851228的博客 1万+

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

数据结构:带头双向循环链表的实现

图示方框为头节点,不添加任何有效数据,头节点的前驱指向3的位置,3的后驱指向头节点,图示就是带头双向循环链表了。遍历链表直到遍历至头节点,若找到要找的值,就返回该地址,遍历完还没有找到就返回NULL。之前说的链表里最后一个节点指向空指针,循环链表里最后一个结点指向第一个结点的地址。遍历整个链表,注意在释放节点时,要先记录下一个节点,遍历完之后,释放头节点。记录删除结点位置的前一个节点位置以及后一个节点的位置。,第二个节点的prev指向头节点即可完成头删。前一个节点的next指向后一个节点,

guai_guai_guai的博客 1065

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

数据结构: 线性表(带头双向循环链表实现)

文章实现了带头双向循环链表, 附有函数接口实现解析

想学好c++的oMen的博客 945

数据结构_第四关:带头双向循环链表的实现

链表中的带头、双向、循环链表的实现,附源代码参考学习

weixin_60630270的博客 812

【数据结构:链表】——带头双向循环链表的实现(C语言)

本片接上一篇【数据结构:链表】——无头单向非循环链表的实现(C语言) 1、链表实现 带头双向循环链表: 带头双向循环链表:结构最复杂,一般用在单独存储数据。实际中使用的链表数据结构,都是带头双向 循环链表。另外这个结构虽然结构复杂,但是使用代码实现以后会发现结构会带来很多优势,实现反而 简单了,后面我们代码实现了就知道了。 2、代码实现 从上图我们可以看出双向链表的节点数据结构就有了些许不同...

紫阳战君的博客 757

数据结构 笔记:双向循环链表的实现

双向循环链表的设计思路 -数据结点之间在逻辑上构成双向循环链表,头结点仅用于结点的定位。 实现思路 -通过模板定义DualCircleList 类,继承自DualLinkList类 -在DualCircleList 内部使用Linux内核链表进行实现 -使用struct llist_head定义DualCircleList的头结点 -特殊处理:循环遍历时忽略头结点  实现要点 ...

Qiuery的博客 265

数据结构:双向循环链表( Double Circular Linked List)及其实现

双向循环链表是一种更高级的链表结构,它就像一条双向环形跑道,每节车厢(节点)都有两个挂钩(指针),一个指向下一节车厢,另一个指向上一节车厢。数据:存储实际的数据(比如数字、字符串等)。前驱指针:指向前一个节点的地址。后继指针:指向下一个节点的地址。链表的最后一个节点的后继指针指向头节点,头节点的前驱指针指向最后一个节点,形成一个双向闭环。正因为如此,双向循环链表可以从任意节点开始,向前或向后无限遍历。下面是一个双向循环链表的示意图:复制。

weixin_57194914的博客 1067

【数据结构初阶】:带头双向循环链表(用C语言实现,附图详解)

文章目录一、带头双向循环链表二、带头双向循环链表实现思路三、链表指针和结点内存布局图四、带头双向循环链表的初始化五、带头双向循环链表接口实现:1.尾部插入数据2.头部插入数据3.尾部删除数据4.头部删除数据5.显示数据6.查找数据7.在结点前面插入数据8.删除当前位置数据9.内存释放六、对头插 尾插 头删 尾删的改造七、总结(附源码) 一、带头双向循环链表 前面我们实现了无头单向非循环链表,特性为:结构简单,一般不会单独用来存数据。实际中更多是作为其他数据结构的子结构,如哈希桶、图的邻接表等等。另外这种结构

平凡的指针的博客 1782

数据结构:双向带头循环链表的基本功能实现

带头双向循环链表:结构最复杂,一般用在单独存储数据。实际中使用的链表数据结构,都是带头双向循环链表。另外这个结构虽然结构复杂,但是使用代码实现以后会发现结构会带来很多优势,实现反而简单了。

唐学长的博客 513

java 双向链表_数据结构Java实现:循环链表和双向链表

上篇教程给大家分享了单链表的概念,以及如何用 Java 实现一个单链表的结构。单链表是最基础的一种链表结构,在实际开发中的使用有一些局限性,比如只能单向往后查找节点,如果需要找到某元素的前驱节点,单链表是无法实现的,今天来给大家分享另外两个复杂一些的链表结构:循环链表和双向链表。循环链表循环链表本质上就是一种单链表,两者的不同之处在于链表中最后一个节点的指针指向哪里,在单链表中,末尾节点的指针指向...

weixin_39906878的博客 90

javascript实现数据结构与算法系列:循环链表与双向链表

循环链表(circular linked list) 是另一种形式的链式存储结构。它的特点是表中最后一个结点的指针域指向头结点,整个表形成一个环。 循环链表的操作和线性链表基本一致,仅有细微差别。 wiki 在一个循环链表中, 首节点和末节点被连接在一起。这种方式在单向和双向链表中皆可实现。要转换一个循环链表,你开始于任意一个节点然后沿着列表的任一方向直到返回开始的节点。再来看另一种方法...

LANGZI7758521的专栏 177

数据结构:带头节点双向循环链表的实现(考研)

#include <bits/stdc++.h> using namespace std; class DoubleLinkedCircleList { private: struct node { int val; node *next, *prior; node(int x) { this->val = x; } node() {...

乐行僧的博客 365
上一篇: 数据结构第3章:数制转换的完整代码
下一篇: 数据结构 链式队列的实现与应用举例:报数问题
xifengcode
博客等级 码龄9年 529粉丝 30原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值