c语言双向循环链表
C语言中都有哪些常见的数据结构你都知道几个?
C语⾔中都有哪些常见的数据结构你都知道⼏个?上次在⾯试时被⾯试官问到学了哪些数据结构,那时简单答了栈、队列/(ㄒoㄒ)/~~其它就都想不起来了,今天有空整理了⼀下⼏种常见的数据结构,原来我们学过的数据结构有这么多~⾸先,先来回顾下C语⾔中常见的基本数据类型吧O(∩_∩)OC语⾔的基本数据类型有:整型int,浮点型float,字符型char等等添加描述那么,究竟什么是数据结构呢?数据结构是计算机存储、组织数据的⽅式。
数据结构是指相互之间存在⼀种或多种特定关系的数据元素的集合⼤部分数据结构的实现都需要借助C语⾔中的指针和结构体类型下⾯,进⼊今天的重点啦O(∩_∩)O⼏种常见的数据结构(1)线性数据结构:元素之间⼀般存在元素之间存在⼀对⼀关系,是最常⽤的⼀类数据结构,典型的有:数组、栈、队列和线性表(2)树形结构:结点间具有层次关系,每⼀层的⼀个结点能且只能和上⼀层的⼀个结点相关,但同时可以和下⼀层的多个结点相关,称为“⼀对多”关系,常见类型有:树、堆(3)图形结构:在图形结构中,允许多个结点之间相关,称为“多对多”关系下⾯分别对这⼏种数据结构做⼀个简单介绍:1、线性数据结构:典型的有:数组、栈、队列和线性表(1)数组和链表a、数组:存放着⼀组相同类型的数据,需要预先指定数组的长度,有⼀维数组、⼆维数组、多维数组等b、链表:链表是C语⾔中⼀种应⽤⼴泛的结构,它采⽤动态分配内存的形式实现,⽤⼀组任意的存储单元存放数据元素链表的,⼀般为每个元素增设指针域,⽤来指向后继元素c、数组和链表的区别:从逻辑结构来看:数组必须事先定义固定的长度,不能适应数据动态地增减的情况;链表动态地进⾏存储分配,可以适应数据动态地增减的情况,且可以⽅便地插⼊、删除数据项(数组中插⼊、删除数据项时,需要移动其它数据项)从内存存储来看:(静态)数组从栈中分配空间(⽤NEW创建的在堆中), 对于程序员⽅便快速,但是⾃由度⼩;链表从堆中分配空间, ⾃由度⼤但是申请管理⽐较⿇烦从访问⽅式来看:数组在内存中是连续存储的,因此,可以利⽤下标索引进⾏随机访问;链表是链式存储结构,在访问元素的时候只能通过线性的⽅式由前到后顺序访问,所以访问效率⽐数组要低(2)栈、队列和线性表:可采⽤顺序存储和链式存储的⽅法进⾏存储顺序存储:借助数据元素在存储空间中的相对位置来表⽰元素之间的逻辑关系链式存储:借助表⽰数据元素存储地址的指针表⽰元素之间的逻辑关系a、栈:只允许在序列末端进⾏操作,栈的操作只能在栈顶进⾏,⼀般栈⼜被称为后进先出或先进后出的线性结构顺序栈:采⽤顺序存储结构的栈称为顺序栈,即需要⽤⼀⽚地址连续的空间来存储栈的元素,顺序栈的类型定义如下:添加描述链栈:采⽤链式存储结构的栈称为链栈:添加描述b、队列:只允许在序列两端进⾏操作,⼀般队列也被称为先进先出的线性结构循环队列:采⽤顺序存储结构的队列,需要按队列可能的最⼤长度分配存储空空,其类型定义如下:添加描述 链队列:采⽤链式存储结构的队列称为链队列,⼀般需要设置头尾指针只是链表的头尾结点:添加描述c、线性表:允许在序列任意位置进⾏操作,线性表的操作位置不受限制,线性表的操作⼗分灵活,常⽤操作包括在任意位置插⼊和删除,以及查询和修改任意位置的元素顺序表:采⽤顺序存储结构表⽰的线性表称为顺序表,⽤⼀组地址连续的存储单元⼀次存放线性表的数据元素,即以存储位置相邻表⽰位序相继的两个元素之间的前驱和后继关系,为了避免移动元素,⼀般在顺序表的接⼝定义中只考虑在表尾插⼊和删除元素,如此实现的顺序表也可称为栈表:添加描述线性表:⼀般包括单链表、双向链表、循环链表和双向循环链表单链表:添加描述 双向链表:添加描述线性表两种存储结构的⽐较:顺序表: 优点:在顺序表中,逻辑中相邻的两个元素在物理位置上也相邻,查找⽐较⽅便,存取任⼀元素的时间复杂度都为O(1) 缺点:不适合在任意位置插⼊、删除元素,因为需要移动元素,平均时间复杂度为O(n)链表: 优点:在链接的任意位置插⼊或删除元素只需修改相应指针,不需要移动元素;按需动态分配,不需要按最⼤需求预先分配⼀块连续空空 缺点:查找不⽅便,查找某⼀元素需要从头指针出发沿指针域查找,因此平均时间复杂度为O(n)2、树形结构:结点间具有层次关系,每⼀层的⼀个结点能且只能和上⼀层的⼀个结点相关,但同时可以和下⼀层的多个结点相关,称为“⼀对多”关系,常见类型有:树、堆(1)⼆叉树:⼆叉树是⼀种递归数据结构,是含有n(n>=0)个结点的有限集合,⼆叉树具有以下特点:⼆叉树可以是空树;⼆叉树的每个结点都恰好有两棵⼦树,其中⼀个或两个可能为空;⼆叉树中每个结点的左、右⼦树的位置不能颠倒,若改变两者的位置,就成为另⼀棵⼆叉树(2)完全⼆叉树:从根起,⾃上⽽下,⾃左⽽右,给满⼆叉树的每个结点从1到n连续编号,如果每个结点都与深度为k的满⼆叉树中编号从1⾄n的结点⼀⼀对应,则称为完全⼆叉树a、采⽤顺序存储结构:⽤⼀维数组存储完全⼆叉树,结点的编号对于与结点的下标(如根为1,则根的左孩⼦为2*i=2*1=2,右孩⼦为2*i+1=2*1+1=2)添加描述b、采⽤链式存储结构:⼆叉链表:添加描述三叉链表:它的结点⽐⼆叉链表多⼀个指针域parent,⽤于执⾏结点的双亲,便于查找双亲结点添加描述两种存储结构⽐较:对于完全⼆叉树,采⽤顺序存储结构既能节省空间,⼜可利⽤数组元素的下标值确定结点在⼆叉树中的位置及结点之间的关系,但采⽤顺序存储结构存储⼀般⼆叉树容易造成空间浪费,链式结构可以克服这个缺点(3)⼆叉查找树:⼆叉查找树⼜称⼆叉排序树,或者是⼀课空⼆叉树,或者是具有如下特征的⼆叉树:a、若它的左⼦树不空,则左⼦树上所有结点的值均⼩于根结点的值b、若它的右⼦树不空,则右⼦树上所有结点的值均⼤于根结点的值c、它的左、右⼦树也分别是⼆叉查找树(4)平衡⼆叉树:平衡⼆叉查找树简称平衡⼆叉树,平衡⼆叉树或者是棵空树,或者是具有下列性质的⼆叉查找树:它的左⼦树和右⼦树都是平衡⼆叉树,且左⼦树和右⼦树的⾼度之差的绝对值不超过1添加描述平衡⼆叉树的失衡及调整主要可归纳为下列四种情况:LL型、RR型、LR型、RL型(5)树:树是含有n(n>=0)个结点的有限集合,在任意⼀棵⾮空树种: a、有且仅有⼀个特定的称为根的结点b、当n>1时,其余结点可分为m(m>0)个互不相交的有限集T1,T2,...,Tm,其中每⼀个集合本⾝⼜是⼀棵树,并且T1,T2,...,Tm称为根的⼦树(6)堆:堆是具有以下特性的完全⼆叉树,其所有⾮叶⼦结点均不⼤于(或不⼩于)其左右孩⼦结点。
C语言 第7章 多重循环
当 y10 <=10
循环变量y5赋初值y5=0 当 y5 <=20
y20*20+y10*10+ y5*5==100?
True
False
输出y20,y10,y5 的组合
y5++ y10++ y20++
例7.3代码
C语言案例教程
main( ) {
int a, b, c; for ( a=0;a<=5; a++) {
7.3 多重循环举例 C语言案例教程
• 【例7.3】银行换零钱。假定你拿1张百元钞票到银行换
零,要求是必须换成若干张20元、10元和5元。请编写程
序,找出所有可能的找零组合,如1张20元,5张10元,6
张5元。
定义循环变量y20,y10,y5
循环变量y20赋初值y20=0
当 y20 <= 5 循环变量y10赋初值y10=0
1 12 123 1234 12345 ……
循环变量x赋初值x=2
当 x <= n
先假设x是素数:flag=1
循环变量y赋初值y=2
当 y<x
True
x%y==0? False
flag=0 True
y++ flag==1?
False
输出x x++
• main()
•{
•
int x, y,n,flag;
•
scanf("%d", &n);
•
for ( x=2; x<=n; x++)
• 编程点拨:
– 首先要对2到n间的每个数进行一下判断,如果是素数,则输出,否则继续判断 下一个数。可以用一个循环来控制数从2变化到n(取循环变量为x)。
[转载整理]C语言链表实例
[转载整理]C语⾔链表实例 C语⾔链表有单链表、双向链表、循环链表。
单链表由数据域和指针域组成,数据域存放数据,指针域存放该数据类型的指针便于找到下⼀个节点。
双链表则含有头指针域、数据域和尾指针域,域单链表不同,双链表可以从后⼀个节点找到前⼀个节点,⼆单链表则不⾏。
循环链表就是在单链表的基础上,将头结点的地址指针存放在最后⼀个节点的指针域⾥以,此形成循环。
此外还有双向循环链表,它同时具有双向链表和循环链表的功能。
单链表如:链表节点的数据结构定义struct node{int num;struct node *p;} ;在此链表节点的定义中,除⼀个整型的成员外,成员p是指向与节点类型完全相同的指针。
※在链表节点的数据结构中,⾮常特殊的⼀点就是结构体内的指针域的数据类型使⽤了未定义成功的数据类型。
这是在C中唯⼀规定可以先使⽤后定义的数据结构。
链表实例代码:1// 原⽂地址 /wireless-dragon/p/5170565.html2 #include<stdio.h>3 #include<stdlib.h>4 #include<string.h>56 typedef int elemType;//定义存⼊的数据的类型可以是int char78 typedef struct NODE{ //定义链表的结构类型9 elemType element;10struct NODE *next;11 }Node;1213/************************************************************************/14/* 以下是关于线性表链接存储(单链表)操作的19种算法 */1516/* 1.初始化线性表,即置单链表的表头指针为空 */17/* 2.创建线性表,此函数输⼊负数终⽌读取数据*/18/* 3.打印链表,链表的遍历*/19/* 4.清除线性表L中的所有元素,即释放单链表L中所有的结点,使之成为⼀个空表 */20/* 5.返回单链表的长度 */21/* 6.检查单链表是否为空,若为空则返回1,否则返回0 */22/* 7.返回单链表中第pos个结点中的元素,若pos超出范围,则停⽌程序运⾏ */23/* 8.从单链表中查找具有给定值x的第⼀个元素,若查找成功则返回该结点data域的存储地址,否则返回NULL */24/* 9.把单链表中第pos个结点的值修改为x的值,若修改成功返回1,否则返回0 */25/* 10.向单链表的表头插⼊⼀个元素 */26/* 11.向单链表的末尾添加⼀个元素 */27/* 12.向单链表中第pos个结点位置插⼊元素为x的结点,若插⼊成功返回1,否则返回0 */28/* 13.向有序单链表中插⼊元素x结点,使得插⼊后仍然有序 */29/* 14.从单链表中删除表头结点,并把该结点的值返回,若删除失败则停⽌程序运⾏ */30/* 15.从单链表中删除表尾结点并返回它的值,若删除失败则停⽌程序运⾏ */31/* 16.从单链表中删除第pos个结点并返回它的值,若删除失败则停⽌程序运⾏ */32/* 17.从单链表中删除值为x的第⼀个结点,若删除成功则返回1,否则返回0 */33/* 18.交换2个元素的位置 */34/* 19.将线性表进⾏冒排序 */35363738/*注意检查分配到的动态内存是否为空*/3940414243/* 1.初始化线性表,即置单链表的表头指针为空 */44void initList(Node **pNode)45 {46 *pNode=NULL;47 printf("initList函数执⾏,初始化成功\n");48 }4950/* 2.创建线性表,此函数输⼊负数终⽌读取数据*/51 Node *creatList(Node *pHead)52 {53 Node *p1,*p2;54 p1=p2=(Node *)malloc(sizeof(Node));55if(p1 == NULL || p2 ==NULL)57 printf("内存分配失败\n");58 exit(0);59 }60 memset(p1,0,sizeof(Node));6162 scanf("%d",&p1->element);63 p1->next=NULL;6465while(p1->element >0) //输⼊的值⼤于0则继续,否则停⽌66 {67if(pHead == NULL)//空表,接⼊表头68 {69 pHead=p1;70 }71else72 {73 p2->next=p1;74 }7576 p2=p1;77 p1=(Node *)malloc(sizeof(Node));7879if(p1==NULL||p2==NULL)80 {81 printf("内存分配失败\n");82 exit(0);83 }84 memset(p1,0,sizeof(Node));85 scanf("%d",&p1->element);86 p1->next=NULL;87 }88 printf("CreatList函数执⾏,链表创建成功\n");89return pHead;90 }9192/* 3.打印链表,链表的遍历*/93void printList(Node *pHead)94 {95if(NULL==pHead)96 {97 printf("PrintList函数执⾏,链表为空\n");98 }99else100 {101while(NULL!=pHead)102 {103 printf("%d\n",pHead->element);104 pHead=pHead->next;105 }106 }107108 }109110111/* 4.清除线性表L中的所有元素,即释放单链表L中所有的结点,使之成为⼀个空表 */ 112void clearList(Node *pHead)113 {114 Node *pNext;115116if(pHead==NULL)117 {118 printf("clearList函数执⾏,链表为空\n");119return;120 }121while(pHead->next!=NULL)122 {123 pNext=pHead->next;124free(pHead);125 pHead=pNext;126 }127 printf("clearList函数执⾏,链表已经清除!\n");128129 }130131/* 5.返回链表的长度*/132int sizeList(Node *pHead)133 {134int size=0;135136while(pHead!=NULL)137 {138 size++;139 pHead=pHead->next;141 printf("sizelist函数执⾏,链表长度为%d\n",size);142return size;143 }144145/* 6.检查单链表是否为空,若为空则返回1,否则返回0 */146int isEmptyList(Node *pHead)147 {148if(pHead==NULL)149 {150 printf("isEmptylist函数执⾏,链表为空!\n");151return1;152 }153154else155 printf("isEmptylist函数执⾏,链表⾮空!\n");156return0;157158 }159160/* 7.返回链表中第post节点的数据,若post超出范围,则停⽌程序运⾏*/161int getElement(Node *pHead,int pos)162 {163int i=0;164if(pos<1)165 {166 printf("getElement函数执⾏,pos值⾮法!");167return0;168 }169if(pHead==NULL)170 {171 printf("getElement函数执⾏,链表为空!");172 }173174while (pHead!=NULL)175 {176 ++i;177if(i==pos)178 {179break;180 }181 pHead=pHead->next;182 }183if(i<pos)184 {185 printf("getElement函数执⾏,pos值超出链表长度\n");186return0;187 }188 printf("getElement函数执⾏,位置%d中的元素为%d\n",pos,pHead->element);189190return1;191 }192193//8.从单⼀链表中查找具有给定值x的第⼀个元素,若查找成功后,返回该节点data域的存储位置,否则返回NULL 194 elemType *getElemAddr(Node *pHead,elemType x)195 {196if(NULL==pHead)197 {198 printf("getEleAddr函数执⾏,链表为空");199return NULL;200 }201if(x<0)202 {203 printf("getEleAddr函数执⾏,给定值x不合法\n");204return NULL;205 }206while((pHead->element!=x)&&(NULL!=pHead->next))//判断链表是否为空,并且是否存在所查找的元素207 {208 pHead=pHead->next;209 }210if(pHead->element!=x)211 {212 printf("getElemAddr函数执⾏,在链表中没有找到x值\n");213return NULL;214 }215else216 {217 printf("getElemAddr函数执⾏,元素%d的地址为0x%x\n",x,&(pHead->element));218 }219return &(pHead->element);220221 }222223224/*9.修改链表中第pos个点X的值,如果修改成功,则返回1,否则返回0*/225int modifyElem(Node *pNode,int pos,elemType x)226 {227 Node *pHead;228 pHead=pNode;229int i=0;230if(NULL==pHead)231 {232 printf("modifyElem函数执⾏,链表为空\n");233return0;234 }235236if(pos<1)237 {238 printf("modifyElem函数执⾏,pos值⾮法\n");239return0;240 }241242while(pHead!= NULL)243 {244 ++i;245if(i==pos)246 {247break;248 }249 pHead=pHead->next;250 }251252if(i<pos)253 {254 printf("modifyElem函数执⾏,pos值超出链表长度\n");255return0;256 }257 pNode=pHead;258 pNode->element=x;259 printf("modifyElem函数执⾏,修改第%d点的元素为%d\n",pos,x);260261return1;262263 }264265/* 10.向单链表的表头插⼊⼀个元素 */266int insertHeadList(Node **pNode,elemType insertElem)267 {268 Node *pInsert;269 pInsert=(Node *)malloc(sizeof(Node));270if(pInsert==NULL) exit(1);271 memset(pInsert,0,sizeof(Node));272 pInsert->element=insertElem;273 pInsert->next=*pNode;274 *pNode=pInsert;275 printf("insertHeadList函数执⾏,向表头插⼊元素%d成功\n",insertElem);276return1;277 }278279/* 11.向单链表的末尾添加⼀个元素 */280int insertLastList(Node *pNode,elemType insertElem)281 {282 Node *pInsert;283 Node *pHead;284 Node *pTmp;285286 pHead=pNode;287 pTmp=pHead;288 pInsert=(Node *)malloc(sizeof(Node));289if(pInsert==NULL) exit(1);290 memset(pInsert,0,sizeof(Node));291 pInsert->element=insertElem;292 pInsert->next=NULL;293while(pHead->next!=NULL)294 {295 pHead=pHead->next;296 }297 pHead->next=pInsert;298 printf("insertLastList函数执⾏,向表尾插⼊元素%d成功!\n",insertElem);299return1;300 }301302/* 12.向单链表中第pos个结点位置插⼊元素为x的结点,若插⼊成功返回1,否则返回0*/ 303int isAddPos(Node *pNode,int pos,elemType x)304 {305 Node *pHead;306 pHead=pNode;307 Node *pTmp;308int i=0;309310if(NULL==pHead)311 {312 printf("AddPos函数执⾏,链表为空\n");313return0;314 }315316if(pos<1)317 {318 printf("AddPos函数执⾏,pos值⾮法\n");319return0;320 }321322while(pHead!=NULL)323 {324 ++i;325if(i==pos)326break;327 pHead=pHead->next;328 }329330if(i<pos)331 {332 printf("AddPos函数执⾏,pos值超出链表长度\n");333return0;334 }335336 pTmp=(Node *)malloc(sizeof(Node));337if(pTmp==NULL) exit(1);338 memset(pTmp,0,sizeof(Node));339 pTmp->next=pHead->next;340 pHead->next=pTmp;341 pTmp->element=x;342343 printf("AddPos函数执⾏成功,向节点%d后插⼊数值%d\n",pos,x); 344return1;345 }346347/* 13.向有序单链表中插⼊元素x结点,使得插⼊后仍然有序 */348int OrrderList(Node *pNode,elemType x)349 {350//注意如果此数值要排到⾏尾要修改本代码351 Node *pHead;352 pHead=pNode;353 Node *pTmp;354355if(NULL==pHead)356 {357 printf("OrrderList函数执⾏,链表为空\n");358return0;359 }360361if(x<1)362 {363 printf("OrrderList函数执⾏,x值⾮法\n");364return0;365 }366367while(pHead!=NULL)368 {369if((pHead->element)>=x)370break;371 pHead=pHead->next;372 }373374375if(pHead==NULL)376 {377 printf("OrrderList函数查找完毕,该函数中没有该值\n");378return0;379 }380381382 pTmp=(Node *)malloc(sizeof(Node));383if(pTmp==NULL) exit(1);384 memset(pTmp,0,sizeof(Node));385 pTmp->next=pHead->next;386 pHead->next=pTmp;387 pTmp->element=x;388389 printf("OrrderList函数成功插⼊数值%d\n",x);390return1;391 }392393/*14.从单链表中删除表头结点,并把该结点的值返回,若删除失败则停⽌程序运⾏*/ 394int DelHeadList(Node **pList)395 {396 Node *pHead;397 pHead=*pList;398if(pHead!=NULL)399 printf("DelHeadList函数执⾏,函数⾸元素为%d删除成功\n",pHead->element); 400else401 {402 printf("DelHeadList函数执⾏,链表为空!");403return0;404 }405 *pList=pHead->next;406return1;407 }408409/* 15.从单链表中删除表尾结点并返回它的值,若删除失败则停⽌程序运⾏ */410int DelLastList(Node *pNode)411 {412 Node *pHead;413 Node *pTmp;414415 pHead=pNode;416while(pHead->next!=NULL)417 {418 pTmp=pHead;419 pHead=pHead->next;420 }421 printf("链表尾删除元素%d成功!\n",pHead->element);422free(pHead);423 pTmp->next=NULL;424return1;425 }426427/* 16.从单链表中删除第pos个结点并返回它的值,若删除失败则停⽌程序运⾏ */ 428int DelPos(Node *pNode,int pos)429 {430 Node *pHead;431 pHead=pNode;432 Node *pTmp;433434int i=0;435436if(NULL==pHead)437 {438 printf("DelPos函数执⾏,链表为空\n");439return0;440 }441442if(pos<1)443 {444 printf("DelPos函数执⾏,pos值⾮法\n");445return0;446 }447448while(pHead!=NULL)449 {450 ++i;451if(i==pos)452break;453 pTmp=pHead;454 pHead=pHead->next;455 }456457if(i<pos)458 {459 printf("DelPos函数执⾏,pos值超出链表长度\n");460return0;461 }462 printf("DelPos函数执⾏成功,节点%d删除数值%d\n",pos,pHead->element); 463 pTmp->next=pHead->next;464free(pHead);465return1;466 }467468/* 17.从单链表中删除值为x的第⼀个结点,若删除成功则返回1,否则返回0 */469int Delx(Node **pNode,int x)470 {471 Node *pHead;472 Node *pTmp;473 pHead=*pNode;474int i=0;475476if(NULL==pHead)477 {478 printf("Delx函数执⾏,链表为空");479return0;480 }481if(x<0)482 {483 printf("Delx函数执⾏,给定值x不合法\n");484return0;485 }486while((pHead->element!=x)&&(NULL!=pHead->next))//判断链表是否为空,并且是否存在所查找的元素487 {488 ++i;489 pTmp=pHead;490 pHead=pHead->next;491 }492if(pHead->element!=x)493 {494 printf("Delx函数执⾏,在链表中没有找到x值\n");495return0;496 }497if((i==0)&&(NULL!=pHead->next))498 {499 printf("Delx函数执⾏,在链表⾸部找到此元素,此元素已经被删除\n");500 *pNode=pHead->next;501free(pHead);502return1;503 }504 printf("Delx函数执⾏,⾸个为%d元素被删除\n",x);505 pTmp->next=pHead->next;506free(pHead);507return1;508 }509510/* 18.交换2个元素的位置 */511int exchange2pos(Node *pNode,int pos1,int pos2)512 {513 Node *pHead;514int *pTmp;515int *pInsert;516int a;517int i=0;518519if(pos1<1||pos2<1)520 {521 printf("DelPos函数执⾏,pos值⾮法\n");522return0;523 }524525 pHead=pNode;526while(pHead!=NULL)527 {528 ++i;529if(i==pos1)530break;531 pHead=pHead->next;532 }533534if(i<pos1)535 {536 printf("DelPos函数执⾏,pos1值超出链表长度\n");537return0;538 }539540 pTmp=&(pHead->element);541 i=0;542 pHead=pNode;543while(pHead!=NULL)544 {545 ++i;546if(i==pos2)547break;548 pHead=pHead->next;549 }550551if(i<pos2)552 {553 printf("DelPos函数执⾏,pos2值超出链表长度\n");554return0;555 }556557 pInsert=&(pHead->element);558 a=*pTmp;559 *pTmp=*pInsert;560 *pInsert=a;561562 printf("DelPos函数执⾏,交换第%d个和第%d个pos点的值\n",pos1,pos2); 563return1;564 }565566int swap(int *p1,int *p2)567 {568int a;569if(*p1>*p2)570 {571 a=*p1;572 *p1=*p2;573 *p2=a;574 }575return0;576 }577578/* 19.将线性表进⾏冒泡排序 */579int Arrange(Node *pNode)580 {581 Node *pHead;582 pHead=pNode;583584int a=0,i,j;585586if(NULL==pHead)587 {588 printf("Arrange函数执⾏,链表为空\n");589return0;590 }591592while(pHead!=NULL)593 {594 ++a;595 pHead=pHead->next;596 }597598 pHead=pNode;599for(i=0;i<a-1;i++)600 {601for(j=1;j<a-i;j++)602 {603 swap(&(pHead->element),&(pHead->next->element));604 pHead=pHead->next;605 }606 pHead=pNode;607 }608 printf("Arrange函数执⾏,链表排序完毕!\n");609return0;610 }611612int main()613 {614 Node *pList=NULL;615int length=0;616617 elemType posElem;618619 initList(&pList);620 printList(pList);621622 pList=creatList(pList);623 printList(pList);624625 sizeList(pList);626 printList(pList);627628 isEmptyList(pList);629630631 posElem=getElement(pList,3);632 printList(pList);633634 getElemAddr(pList,5);635636 modifyElem(pList,4,1);637 printList(pList);638639 insertHeadList(&pList,5);640 printList(pList);641642 insertLastList(pList,10);643 printList(pList);644645 isAddPos(pList,4,5); 646 printList(pList);647648 OrrderList(pList,6);649 printList(pList);650651 DelHeadList(&pList); 652 printList(pList);653654 DelLastList(pList);655 printList(pList);656657 DelPos(pList,5);658 printList(pList);659660 Delx(&pList,5);661 printList(pList);662663 exchange2pos(pList,2,5); 664 printList(pList);665666 Arrange(pList);667 printList(pList);668669 clearList(pList);670return0;671 }。
循环双链表特点
循环双链表特点循环双链表是一种特殊的数据结构,它具有循环和双向链表的特点。
循环双链表中的每个节点都包含两个指针,一个指向前一个节点,一个指向后一个节点。
最后一个节点的后指针指向头节点,头节点的前指针指向最后一个节点,从而形成了一个闭环。
循环双链表的特点如下:1. 双向性:每个节点都有两个指针,分别指向前一个节点和后一个节点。
这样可以方便地在任意位置插入或删除节点,而不需要像单链表那样需要遍历找到前驱节点。
2. 循环性:循环双链表是一个闭环,即最后一个节点的后指针指向头节点,头节点的前指针指向最后一个节点。
这样可以方便地进行循环遍历,不需要判断是否到达了链表的末尾。
3. 动态性:循环双链表可以动态地增加或删除节点,而不需要预先指定链表的长度。
4. 灵活性:循环双链表可以在任意位置插入或删除节点,不受限于只能在链表的头部或尾部进行操作。
这样可以方便地实现栈、队列等数据结构。
5. 代码实现简单:相比于其他数据结构,循环双链表的代码实现相对简单,只需要处理好节点之间的指针关系即可。
循环双链表的应用领域非常广泛,特别是在需要频繁插入和删除节点的场景中,循环双链表能够提供高效的插入和删除操作。
下面以几个具体的应用场景来展开对循环双链表的解释和扩展。
1. 缓存替换算法:循环双链表可以用于实现LRU(Least Recently Used)缓存替换算法。
LRU算法中,当缓存满时,需要替换掉最近最少使用的数据。
循环双链表可以维护数据的访问顺序,每次访问一个数据时,将其移到链表的头部;当缓存满时,删除链表尾部的数据即可。
这样就可以保证链表头部的数据是最近访问的数据,尾部的数据是最久未访问的数据。
2. 轮播图:循环双链表可以用于实现轮播图功能。
轮播图需要循环展示多张图片,循环双链表正好可以满足这个需求。
每个节点表示一张图片,节点之间通过指针连接起来形成一个循环链表。
通过不断地遍历链表,可以实现图片的自动切换。
3. 约瑟夫环问题:循环双链表可以用于解决约瑟夫环问题。
c语言双循环的简单例子
c语言双循环的简单例子从代码所示为常见的for语句双重循环,循环原理如下1,对于给二维数组赋值部分,第一次i=0,判断i<3值为真,然后执行二重循环语句,j=0,判断j<2结果为真,因此执行下面的循环体语句,a[0][0]=0+0=0,j++2,第二次循环依旧是在j循环部分执行,j=1,判断j<2结果为真,因此执行下面的循环体语句,a[0][1]=0+1=1,j++3,第三次循环依旧是在j循环部分执行,j=2,判断j<2结果为假,退出j部分循环,i++4,第四次循环,i=1,判断i<3结果为真,然后执行j部分二重循环语句,j=0;判断j<2结果为真,因此执行下面的循环体语句,a[1][0]=1+0=1,j++5,第五次循环,i=1,判断j<2结果为真,执行循环体语句,a[1][1]=1+1=2,j++本文实例讲述了C++双向循环列表用法。
分享给大家供大家参考。
具体如下:1 2 3 4 5 6 7 8 9 1/*双向循环链表*/#include <iostream> using namespace std;1 1 12 13 14 15 16 17 18 19 2 0 2 1 2 2 2 3 2 4 2 5 2 6 2 7 2 8 2 9 3 0 3 1 //结构体构造链表的指针域和数据域struct ChainNode{int data; //节点数据ChainNode *left; //节点的前驱指针ChainNode *right; //节点的后继指针};////////////创建n个双向循环链表并返回链表头指针///////// ChainNode* CreateNode(int n){ChainNode *head = NULL; //链表头节点ChainNode *pCur=NULL,*pNew=NULL; //当前节点,新建节点//初始化头结点的前驱和后继节点都为NULLif(n<1) //没有节点返回头节点{return head;}//创建头节点并将器左右指针指向空head = new ChainNode;head->left = NULL;head->right = NULL;2 3 3 3 4 3 5 3 6 3 7 3 8 3 9 4 0 4 1 4 2 4 3 4 4 4 5 4 6 4 7 4 8 4 9 5 0 5 1 5 2 5head->data = 0;pCur = head;//为防止指针互指带来的混乱,用pCur节点保存了头节点也表示当前指针移动到了头指针//创建n个节点并连接成链表for(int i=0; i<n; i++){pNew = new ChainNode; //创建一个新节点cout<<"请输入数据:";cin>>pNew->data;pCur->right = pNew; //头指针的右指针指向新建节点pNew->left = pCur; //新建节点的左指针执行头节点pNew->right = NULL; //用于最后和头指针进行交换pCur = pNew; //指针往下移动}//最后将头指针的左指针指向最后一个节点,//最后一个节点的有指针指向头指针,构成循环head->left = pCur;pCur->right = head;return head;}5 4 5 5 56 57 58 59 6 0 6 1 6 2 6 3 6 4 6 5 6 6 6 7 6 8 6 9 7 0 7 1 7 2 7 3 7 4 //////////////输出链表头节点///////////////////////void OutList(ChainNode *head) //参数为头指针从头指针开始{cout<<"链表元素输出如下:"<<endl;ChainNode *pCur = head->right;//重第一个节点开始输出//没有指向空节点,则链表没结束输出链表元素while(pCur->right != head){cout<<pCur->data<<" ";pCur = pCur->right;//当前节点指向下一个节点可以遍历链表}cout<<pCur->data<<endl;//输入最后一个元素,它的右指针执行head}///////在双向循环链表后添加n个节点//////ChainNode* AddNode(ChainNode* head, int n){ChainNode *pNew,*pCur;//新添加节点和当前节点5 767 7 78 79 8 0 8 1 8 2 8 3 8 4 8 5 8 6 8 7 8 8 8 9 9 0 9 1 9 2 9 3 9 4 9 5 9pCur = head;//移动到最节点while(pCur->right != head){pCur = pCur->right;//当前节点往下移动一直移到最后一个节点}//新添加n个节点并插入链表for(int i=0; i<n; i++){pNew = new ChainNode;cout<<"输入要添加的节点元素:";cin>>pNew->data;pCur->right = pNew; //头指针的右指针指向新建节点pNew->left = pCur; //新建节点的左指针执行头节点pNew->right = NULL; //用于最后和头指针进行交换pCur = pNew; //指针往下移动}//最后将头指针的左指针指向最后一个节点,//最后一个节点的有指针指向头指针,构成循环head->left = pCur;9 7 9 8 9 9 1 0 0 1 0 1 1 0 2 1 0 3 1 0 4 1 0 5 1 0 6 1 0 7 1 0 8 1 0 9 1 1 0 1 1 1pCur->right = head;return head;}/////在双向循环链表中删除一个节点///////ChainNode* DeleteNode(ChainNode* head, unsigned num) //删除第num个节点{ChainNode *pNew,*pCur,*temp;//新添加节点和当前节点 ,临时交换节点pCur = head;int ncount = 0;//移动到第num-1个节点while(1){ncount++;pCur = pCur->right; //当前节点往下移动if(num == ncount){break; //此时pCur还是指向了第num个节点}}1 2 1 1 3 1 1 4 1 1 5 1 1 6 1 1 7 1 1 8 1 1 9 1 2 0 1 2 1 1 2 2 1 2 3 1 2 4 1 2 5 1//当前节点的前一个节点的右指针指向当前节点的下一个节点//当前节点的下一个节点的左指针指向当前节点的上一个节点构成连接//最后删除当前节点(pCur->left)->right = pCur->right;(pCur->right)->left = pCur->left;delete pCur;return head;}int main(){int num;//创建num个节点并显示cout<<"输入要创建的链表节点个数:";cin>>num;ChainNode *head = CreateNode(num);OutList(head);//往链表后添加n个节点int addnum;cout<<"输入要添加的节点个数:";cin>>addnum;AddNode(head, addnum);6 1 27 1 28 1 29 1 3 0 1 3 1 1 3 2 1 3 3 1 3 4 1 3 5 1 3 6 1 3 7 1 3 8 1 3 9 1 4OutList(head);//删除链表的第del个元素int del;cout<<"输入要删除的第几个位置的节点:"; cin>>del;DeleteNode (head, del);OutList(head);system("pause");return0;}。
c语言中linklist类型
c语言中linklist类型LinkList类型是C语言中常用的数据结构之一,用于表示链表。
链表是一种动态数据结构,它可以根据需要动态地分配和释放内存空间,比较灵活。
在本文中,我们将深入探讨LinkList类型及其相关操作。
一、什么是链表链表是一种由节点组成的数据结构,每个节点包含数据和指向下一个节点的指针。
链表中的节点可以按照任意顺序存储,通过指针将它们连接起来。
与数组相比,链表的插入和删除操作更加高效,但是访问元素的效率较低。
链表分为单向链表和双向链表两种形式,本文主要介绍单向链表。
二、LinkList类型的定义在C语言中,我们通过结构体来定义链表节点的数据结构,具体定义如下:```ctypedef struct Node{int data;struct Node *next;}Node;typedef Node *LinkList;```其中,Node表示链表的节点类型,LinkList表示链表的类型。
三、LinkList类型的常用操作1. 初始化链表初始化链表主要是将链表的头指针置空,表示链表为空。
具体实现如下:```cvoid InitList(LinkList *L){*L = NULL;}```2. 判断链表是否为空判断链表是否为空可以通过判断链表的头指针是否为空来实现。
具体实现如下:```cint ListEmpty(LinkList L){return L == NULL;}```3. 求链表的长度求链表的长度即统计链表中节点的个数。
具体实现如下:```cint ListLength(LinkList L){int count = 0;Node *p = L;while(p != NULL){count++;p = p->next;}return count;}```4. 插入节点插入节点可以在链表的任意位置插入新的节点。
具体实现如下:```cint ListInsert(LinkList *L, int pos, int data){if(pos < 1 || pos > ListLength(*L) + 1){return 0;}Node *p = *L;Node *newNode = (Node*)malloc(sizeof(Node));newNode->data = data;newNode->next = NULL;if(pos == 1){newNode->next = *L;*L = newNode;}else{for(int i = 1; i < pos - 1; i++){p = p->next;}newNode->next = p->next;p->next = newNode;}return 1;}```5. 删除节点删除节点可以删除链表中指定位置的节点。
数据结构中的双向链表实现和应用场景
数据结构中的双向链表实现和应用场景双向链表是一种常用的数据结构,它在许多实际应用中都发挥着重要的作用。
本文将介绍双向链表的实现原理以及一些常见的应用场景。
一、双向链表的实现原理双向链表由一系列节点组成,每个节点包含两个指针,一个指向前一个节点,一个指向后一个节点。
相比于单向链表,双向链表可以实现双向遍历,提高了一些操作的效率。
1.1 节点定义双向链表的节点通常由数据域和两个指针域组成,例如:```struct Node {int data; // 节点数据Node* prev; // 前一个节点指针Node* next; // 后一个节点指针};```1.2 插入操作在双向链表中插入一个节点可以分为两种情况:在表头插入和在表尾插入。
在表头插入时,只需修改原来头节点的prev指针为新节点的地址,并将新节点的next指针指向原头节点即可。
在表尾插入时,需要先找到原来的尾节点,然后将尾节点的next指针指向新节点的地址,并将新节点的prev指针指向尾节点的地址。
1.3 删除操作删除操作与插入操作类似,同样分为在表头和表尾删除节点。
在表头删除时,只需将头节点的next指针指向新的头节点,同时将新头节点的prev指针置为空。
在表尾删除时,需要先找到尾节点的前一个节点,然后将该节点的next指针置为空。
1.4 查找操作双向链表支持从前向后和从后向前两种遍历方式。
从前向后遍历时,我们可以利用节点的next指针不断向后遍历得到所有节点。
同样,从后向前遍历时,可以利用节点的prev指针不断向前遍历得到所有节点。
二、双向链表的应用场景双向链表广泛应用于各种软件和系统中,下面列举了一些常见的应用场景。
2.1 浏览器的历史记录在浏览器中,经常需要记录用户浏览过的网页历史记录。
这时可以使用双向链表来实现。
每当用户访问一个新的网页,就在双向链表中插入一个新节点,同时将新节点的next指针指向前一个节点,prev指针指向后一个节点。
C语言的循环链表和约瑟夫环
C语言的循环链表和约瑟夫环C语言的循环链表和约瑟夫环约瑟夫问题)是一个数学的应用问题,对于学习C语言四非常挺有帮助的,下面是店铺为大家搜集整理出来的有关于C语言的循环链表和约瑟夫环,一起了解下吧!循环链表的实现单链表只有向后结点,当单链表的尾链表不指向NULL,而是指向头结点时候,形成了一个环,成为单循环链表,简称循环链表。
当它是空表,向后结点就只想了自己,这也是它与单链表的主要差异,判断node->next是否等于head。
代码实现分为四部分:1. 初始化2. 插入3. 删除4. 定位寻找代码实现:1 2 3 4 5 6 7 8 9 1 0 1 1 1 2 1 3 1void ListInit(Node *pNode){int item;Node *temp,*target;cout<<"输入0完成初始化"<<endl; cin="">>item;if(!item)return ;if(!(pNode)){ //当空表的时候,head==NULLpNode = new Node ;if(!(pNode))exit(0);//未成功申请pNode->data = item;pNode->next = pNode;}else{//for(target = pNode;target->next!=pNode;target = target->next);4 15 16 17 18 19 2 0 2 1 2 2 2 3 2 4 2 5 2 6 2 7 2 8 2 9 3 0 3 1 3 2 3 3 3 4 3 5 3temp = new Node;if(!(temp))exit(0);temp->data = item;temp->next = pNode;target->next = temp;}}}void ListInsert(Node *pNode,int i){ //参数是首节点和插入位置Node *temp;Node *target;int item;cout<<"输入您要插入的值:"<<endl; cin="">>item;if(i==1){temp = new Node;if(!temp)exit(0);temp->data = item;for(target=pNode;target->next != pNode;target = target->next);temp->next = pNode;target->next = temp;pNode = temp;}else{target = pNode;for (int j=1;j<i-1;++j) target="target-">next;temp = new Node;if(!temp)exit(0);temp->data = item;temp->next = target->next;target->next = temp;}}void ListDelete(Node *pNode,int i){Node *target,*temp;if(i==1){for(target=pNode;target->next!=pNode;target=target ->next);temp = pNode;//保存一下要删除的首节点 ,一会便于释放6 37 38 39 4 0 4 1 4 2 4 3 4 4 4 5 4 6 4 7 4 8 4 9 5 0 5 1 5 2 5 3 5 4 5 5 5 6 5 7 5pNode = pNode->next;target->next = pNode;temp;}else{target = pNode;for(int j=1;j<i-1;++j) target="target-">next;temp = target->next;//要释放的nodetarget->next = target->next->next;temp;}}int ListSearch(Node *pNode,int elem){ //查询并返回结点所在的位置Node *target;int i=1;for(target = pNode;target->data!=elem && target->next!= pNode;++i)target = target->next;if(target->next == pNode && target->data!=elem)return 0;else return i;}</i-1;++j)></i-1;++j)></endl;></endl;>5 96 0 6 1 6 2 6 3 6 4 6 5 6 6 67 68 69 7 0 7 1 7 2 7 3 7 4 7 5 7 6 7 7 7 8 7 9 8约瑟夫问题约瑟夫环(约瑟夫问题)是一个数学的'应用问题:已知n个人(以编号1,2,3…n分别表示)围坐在一张圆桌周围。
双向链表的建立、查找、插入、删除
/*双链表的操作:查询、删除、显示、插入。
*双向链表克服单向链表向前查找结点需要执行时间O(n)的缺点*2008.1.17*/#include <stdio.h>#include <stdlib.h>#include <string.h>#define N 10typedef struct node *ptNode;struct node{char name[20];ptNode lLink,rLink;};/*双链表的结构定义*//*双链表的创建*/ptNode Creat(int n){ptNode head,ptr,newnode;int i;if((head=(ptNode)malloc(sizeof(node))) == NULL){printf("cannot find space!\n");exit(0);}head->name[0] = '\0';//头结点初始化head->lLink = NULL;head->rLink = NULL;ptr = head;for(i=0; i<n; i++){if((newnode=(ptNode) malloc(sizeof(node))) == NULL){printf("cannot find space!\n");exit(0);}ptr->rLink = newnode;//连接新结点printf("Please input the %d man's name: ",i+1);scanf("%s",newnode->name);newnode->lLink = ptr;//定义newnode的连接关系newnode->rLink = NULL;ptr = newnode;}//end forhead->lLink = newnode;ptr->rLink = head;return(head);}/*查找名字的位置*/ptNode Search(ptNode head,char *pEle){ptNode ptr;char *pTemp;ptr = head->rLink;while(ptr != head)//以是否回到头结点为结束条件{pTemp = ptr->name;//pTemp暂存结点的名字地址if(strcmp(pTemp,pEle) == 0){return(ptr);}else{ptr = ptr->rLink;//指向下一结点}}printf("cannot find data!\n");return NULL;}//在选定名字前插入void Insert(ptNode head,char *prior,char *insertEle){ptNode ptr,newnode;if((ptr=Search(head,prior)) ==NULL){printf("Can't find the data to insert!\n");exit(0);}if((newnode=(ptNode)malloc(sizeof(node))) == NULL){printf("Can't arrange memory space!\n");exit(0);}strcpy(newnode->name,insertEle);//给新结点加载值newnode->lLink = ptr->lLink;//前指针指向前结点,先处理以新结点为中心前后关系newnode->rLink = ptr;//新结点后指针指向定位结点(ptr->lLink)->rLink = newnode;//前结点的由指针指向新结点ptr->lLink = newnode;}/*打印输出*/void Print(ptNode head){ptNode ptr;ptr = head->rLink;printf("\nNow the double list is:\n");while(ptr != head){printf("%s ",ptr->name);ptr = ptr->rLink;}printf("\n");}/*删除*/void Delete(ptNode ptr){(ptr->rLink)->lLink = ptr->lLink;//(ptr->rLink)->lLink下一结点的左指针被赋前指针(ptr->lLink)->rLink = ptr->rLink;free (ptr);}/*主函数*/void main(void){int number;char studName[20];char insertName[20];ptNode head,searchpoint;number = N;puts("Please input the size of the list:");scanf("%d",&number);head = Creat(number);Print(head);printf("\nPlease input the name which you want to find:\n");scanf("%s",studName);searchpoint = Search(head,studName);printf("the name you want to find is:%s\n",searchpoint->name);Delete(searchpoint);Print(head);printf("Before which element do you want to insert:\n");scanf("%s",studName);printf("Enter the student name you want to insert:\n");scanf("%s",insertName);Insert(head,studName,insertName);Print(head);puts("\n");}。
数据结构--数组、单链表和双链表介绍以及双向链表
数据结构--数组、单链表和双链表介绍以及双向链表数组:数组有上界和下界,数组的元素在上下界内是连续的。
数组的特点是:数据是连续的;随机访问速度快。
数组中稍微复杂⼀点的是多维数组和动态数组。
对于C语⾔⽽⾔,多维数组本质上也是通过⼀维数组实现的。
⾄于动态数组,是指数组的容量能动态增长的数组;对于C语⾔⽽⾔,若要提供动态数组,需要⼿动实现;⽽对于C++⽽⾔,STL提供了Vector。
单向链表:单向链表(单链表)是链表的⼀种,它由节点组成,每个节点都包含下⼀个节点的指针。
表头为空,表头的后继节点是"节点10"(数据为10的节点),"节点10"的后继节点是"节点20"(数据为10的节点),"节点20"的后继节点是"节点30"(数据为20的节点),"节点30"的后继节点是"节点40"(数据为10的节点),......删除"节点30"删除之前:"节点20" 的后继节点为"节点30",⽽"节点30" 的后继节点为"节点40"。
删除之后:"节点20" 的后继节点为"节点40"。
在"节点10"与"节点20"之间添加"节点15"添加之前:"节点10" 的后继节点为"节点20"。
添加之后:"节点10" 的后继节点为"节点15",⽽"节点15" 的后继节点为"节点20"。
单链表的特点是:节点的链接⽅向是单向的;相对于数组来说,单链表的的随机访问速度较慢,但是单链表删除/添加数据的效率很⾼。
链表(单链表 双向循环)实验报告讲解
数据结构实验报告T1223-3-21余帅实验一实验题目:仅仅做链表部分难度从上到下1.双向链表,带表头,线性表常规操作。
2.循环表,带表头,线性表常规操作。
3.单链表,带表头,线性表常规操作。
实验目的:了解和掌握线性表的逻辑结构和链式存储结构,掌握单链表的基本算法及相关的时间性能分析。
实验要求:常规操作至少有:1.数据输入或建立2.遍历3.插入4.删除必须能多次反复运行实验主要步骤:1、分析、理解给出的示例程序。
2、调试程序,并设计输入数据,测试程序的如下功能:1.数据输入或建立2.遍历3.插入4.删除单链表示意图:headhead head 创建删除双向循环链表示意图:创建程序代码://单链表#include<iostream.h>#include<windows.h>const MAX=5;enum returninfo{success,fail,overflow,underflow,range_error}; int defaultdata[MAX]={11,22,33,44,55};class node{public:int data;node *next;};class linklist{private:node *headp;protected:int count;public:linklist();~linklist();bool empty();void clearlist();returninfo create(void);returninfo insert(int position,const int &item);returninfo remove(int position) ;returninfo traverse(void);};linklist::linklist(){headp = new node;headp->next = NULL;count=0;}linklist::~linklist(){clearlist();delete headp;}bool linklist::empty(){if(headp->next==NULL)return true;elsereturn false;}void linklist::clearlist(){node *searchp=headp->next,*followp=headp;while(searchp->next!=NULL){followp=searchp;searchp=searchp->next;delete followp;}headp->next = NULL;count = 0;}returninfo linklist::create(){node *searchp=headp,*newnodep;for(int i=0;i<MAX;i++){newnodep = new node;newnodep->data = defaultdata[i];newnodep->next = NULL;searchp->next = newnodep;searchp = searchp->next;count++;}searchp->next = NULL;traverse();return success;}returninfo linklist::insert(int position,const int &item) //插入一个结点{if(position<=0 || position>=count)return range_error;node *newnodep=new node,*searchp=headp->next,*followp=headp;for(int i=1; i<position && searchp!=NULL;i++){followp=searchp;searchp=searchp->next;}newnodep->data=item; //给数据赋值newnodep->next=followp->next; //注意此处的次序相关性followp->next=newnodep;count++; //计数器加一return success;}returninfo linklist::remove(int position) //删除一个结点{if(empty())return underflow;if(position<=0||position>=count+1)return range_error;node *searchp=headp->next,*followp=headp; //这里两个指针的初始值设计一前一后for(int i=1; i<position && searchp!=NULL;i++){followp=searchp;searchp=searchp->next;}followp->next=searchp->next; //删除结点的实际语句delete searchp; //释放该结点count--; //计数器减一return success;}returninfo linklist::traverse(void){node *searchp;if(empty())return underflow;searchp = headp->next;cout<<"连表中的数据为:"<<endl;while(searchp!=NULL){cout<<searchp->data<<" ";searchp = searchp->next;}cout<<endl;return success;}class interfacebase{public:linklist listface; //定义一个对象Cskillstudyonfacevoid clearscreen(void);void showmenu(void);void processmenu(void);};void interfacebase::clearscreen(void){system("cls");}void interfacebase::showmenu(void){cout<<"================================"<<endl;cout<<" 功能菜单 "<<endl;cout<<" 1.创建链表 "<<endl;cout<<" 2.增加结点 "<<endl;cout<<" 3.删除结点 "<<endl;cout<<" 4.遍历链表 "<<endl;cout<<" 0.结束程序 "<<endl;cout<<"======================================"<<endl;cout<<"请输入您的选择:";}void interfacebase::processmenu(void){int returnvalue,item,position;char menuchoice;cin >>menuchoice;switch(menuchoice) //根据用户的选择进行相应的操作{case '1':returnvalue=listface.create();if(returnvalue==success)cout<<"链表创建已完成"<<endl;break;case '2':cout<<"请输入插入位置:"<<endl;cin>>position;cout<<"请输入插入数据:"<<endl;cin>>item;returnvalue = listface.insert(position,item);if(returnvalue==range_error)cout<<"数据个数超出范围"<<endl;elsecout<<"操作成功!!!"<<endl;break;case '3':cout<<"输入你要删除的位置:"<<endl;cin>>position;returnvalue = listface.remove(position);if(returnvalue==underflow)cout<<"链表已空"<<endl;else if(returnvalue==range_error)cout<<"删除的数据位置超区范围"<<endl;elsecout<<"操作成功!!!"<<endl;break;case '4':listface.traverse();break;case '0':cout<<endl<<endl<<"您已经成功退出本系统,欢迎再次使用!!!"<<endl;system("pause");exit(1);default:cout<<"对不起,您输入的功能编号有错!请重新输入!!!"<<endl;break;}}void main(){interfacebase interfacenow;linklist listnow;system("color f0");interfacenow.clearscreen();while(1){interfacenow.showmenu();interfacenow.processmenu();system("pause");interfacenow.clearscreen();}}/* 功能:用双向循环链表存储数据1.创建链表2.增加结点3.删除结点4.遍历链表制作人:余帅内容:239行*/#include<iostream.h>#include<windows.h>const MAX=5;enum returninfo{success,fail,overflow,underflow,range_error}; int defaultdata[MAX]={11,22,33,44,55};class node{public:int data;node * next; //指向后续节点node * pre; //指向前面的节点};class linklist{private:node *headp;protected:int count;public:linklist();~linklist();bool empty();void clearlist();returninfo create(void);returninfo insert(int position,const int &item);returninfo remove(int position) ;returninfo traverse(void);};linklist::linklist(){headp = new node;headp->next = NULL;headp->pre = NULL;count=0;}linklist::~linklist(){clearlist();delete headp;}bool linklist::empty(){if(headp->next==NULL)return true;elsereturn false;}void linklist::clearlist(){node *searchp=headp->next,*followp=headp;while(searchp->next!=NULL){followp=searchp;searchp=searchp->next;delete followp;}headp->next = NULL;headp->pre = NULL;count = 0;}returninfo linklist::create(){node *searchp=headp,*newnodep;for(int i=0;i<MAX;i++){newnodep = new node;newnodep->data = defaultdata[i];newnodep->next = NULL;searchp->next = newnodep;newnodep->pre = searchp;searchp = searchp->next;count++;}searchp->next = headp;headp->pre = searchp;traverse();return success;}returninfo linklist::insert(int position,const int &item) //插入一个结点{if(position<=0 || position>count+1)return range_error;node *newnodep=new node;node *searchp=headp->next,*followp=headp;for(int i=1; i<position && searchp!=NULL;i++){followp=searchp;searchp=searchp->next;}newnodep->data=item; //给数据赋值newnodep->next = searchp;searchp->pre = newnodep;followp->next = newnodep;newnodep->pre = followp;count++; //计数器加一return success;}returninfo linklist::remove(int position) //删除一个结点{if(empty())return underflow;if(position<=0||position>=count+1)return range_error;node *searchp=headp->next,*followp=headp; //这里两个指针的初始值设计一前一后for(int i=1; i<position && searchp!=NULL;i++){followp=searchp;searchp=searchp->next;}followp->next=searchp->next; //删除结点的实际语句searchp->next->pre = followp;delete searchp; //释放该结点count--; //计数器减一return success;}returninfo linklist::traverse(void){node *searchp1,*searchp2;if(empty())return underflow;searchp1 = headp;searchp2 = headp;cout<<"连表中的数据为:"<<endl;cout<<"从左至右读取:";while (searchp1->next!=headp ) {searchp1 = searchp1 ->next;cout << searchp1->data<<" ";}cout<<endl;cout<<"从右至左读取:";while (searchp2->pre!=headp ) {searchp2 = searchp2 ->pre;cout << searchp2->data<<" ";}cout<<endl;return success;}class interfacebase{public:linklist listface; //定义一个对象Cskillstudyonface void clearscreen(void);void showmenu(void);void processmenu(void);};void interfacebase::clearscreen(void){system("cls");}void interfacebase::showmenu(void){cout<<"================================"<<endl;cout<<" 功能菜单 "<<endl;cout<<" 1.创建链表 "<<endl;cout<<" 2.增加结点 "<<endl;cout<<" 3.删除结点 "<<endl;cout<<" 4.遍历链表 "<<endl;cout<<" 0.结束程序 "<<endl;cout<<"======================================"<<endl;cout<<"请输入您的选择:";}void interfacebase::processmenu(void){int returnvalue,item,position;char menuchoice;cin >>menuchoice;switch(menuchoice) //根据用户的选择进行相应的操作{case '1':returnvalue=listface.create();if(returnvalue==success)cout<<"链表创建已完成"<<endl;break;case '2':cout<<"请输入插入位置:"<<endl;cin>>position;cout<<"请输入插入数据:"<<endl;cin>>item;returnvalue = listface.insert(position,item);if(returnvalue==range_error)cout<<"数据个数超出范围"<<endl;elsecout<<"操作成功!!!"<<endl;break;case '3':cout<<"输入你要删除的位置:"<<endl;cin>>position;returnvalue = listface.remove(position);if(returnvalue==underflow)cout<<"链表已空"<<endl;else if(returnvalue==range_error)cout<<"删除的数据位置超区范围"<<endl;elsecout<<"操作成功!!!"<<endl;break;case '4':listface.traverse();break;case '0':cout<<endl<<endl<<"您已经成功退出本系统,欢迎再次使用!!!"<<endl;system("pause");exit(1);default:cout<<"对不起,您输入的功能编号有错!请重新输入!!!"<<endl;break;}}void main(){interfacebase interfacenow;linklist listnow;system("color f0");interfacenow.clearscreen();while(1){interfacenow.showmenu();interfacenow.processmenu();system("pause");interfacenow.clearscreen();}}运行结果:1.创建链表:2.增加结点3.删除结点心得体会:本次实验使我们对链表的实质了解更加明确了,对链表的一些基本操作也更加熟练了。
c语言循环引用
c语言循环引用循环引用是指两个或多个对象之间相互引用,形成一个循环链表。
在C语言中,循环引用是一种常见的编程错误,容易导致内存泄漏和程序崩溃。
循环引用的问题在于两个对象互相持有对方的指针,当其中一个对象被释放时,另一个对象仍然持有对方的指针,导致无法释放内存。
这种情况下,内存中的对象会一直存在,占用内存空间,最终导致内存泄漏。
循环引用的典型场景是在面向对象编程中的对象关联关系中。
例如,一个图书馆管理系统中,图书馆和书籍之间是一种循环引用关系。
图书馆对象包含了书籍对象的列表,而每本书籍对象又包含了所属图书馆的指针。
这样,当图书馆对象被释放时,由于书籍对象仍然持有对图书馆对象的引用,导致无法释放内存。
为了解决循环引用的问题,可以采用以下几种方法。
1. 手动解除引用:在程序中显式地解除对象之间的引用关系,确保在释放内存之前将循环引用解除。
2. 弱引用:使用弱引用来代替强引用,避免形成循环引用。
弱引用是指对对象的引用不会增加其引用计数,当对象的引用计数为0时,对象会被自动释放。
3. 使用智能指针:智能指针是一种自动管理内存的指针,可以在对象不再被引用时自动释放内存。
使用智能指针可以避免手动解除引用的繁琐操作,提高代码的可读性和可维护性。
4. 使用垃圾回收机制:垃圾回收机制是一种自动管理内存的机制,可以在运行时自动回收不再使用的对象。
通过垃圾回收机制,可以避免循环引用导致的内存泄漏问题。
在实际编程中,我们应该尽量避免循环引用的产生。
当需要建立对象之间的关联关系时,应该仔细考虑对象之间的依赖关系,避免形成循环引用。
在设计对象的生命周期时,应该合理地管理对象之间的引用关系,确保在对象不再被使用时能够正确释放内存。
循环引用是一种常见的编程错误,容易导致内存泄漏和程序崩溃。
为了避免循环引用的问题,我们可以采取手动解除引用、使用弱引用、使用智能指针或使用垃圾回收机制等方法。
在编程过程中,应该合理设计对象之间的关联关系,避免形成循环引用,确保程序的稳定性和内存的有效使用。
《数据结构C语言版》----第02章
p size=0
head
a0
a1
(a)
...
a n 1 ∧
3.顺序表操作的效率分析
时间效率分析: 算法时间主要耗费在移动元素的操作上,因此计算时间复 杂度的基本操作(最深层语句频度) T(n)= O(移动元素次数) 而移动元素的个数取决于插入或删除元素的位置i. 若i=size,则根本无需移动(特别快); 若i=0,则表中元素全部要后移(特别慢); 应当考虑在各种位置插入(共n+1种可能)的平均移动次 数才合理。
(3)带头结点单链表和不带头结点单链表的比较
1).在带头结点单链表第一个数据元素前插入结点
p head s p head data next a0 x
∧
a1
…
an-1
∧
(a) 插入前
data next a0
∧
a1
…
an-1
∧
s
x
(b) 插入后
2).删除带头结点单链表第一个数据元素结点
p data next head
(5)取数据元素ListGet(L,
i, x)
int ListGet(SeqList L, int i, DataType *x) { if(i < 0 || i > L.size-1) { printf("参数i不合法! \n"); return 0; } else { *x = L.list[i]; return 1; } }
带头结点的双向循环链表操作集
带头结点的双向循环链表操作集带头结点的双向循环链表操作集1. 链表的定义链表是一种数据结构,它由一系列节点组成,每个节点存储数据和指向下一个节点的指针。
链表可以分为单向链表和双向链表。
在双向链表中,每个节点有两个指针,一个指向前一个节点,另一个指向后一个节点。
2. 链表的基本操作2.1 链表的创建创建一个带头结点的双向循环链表,可以按照以下步骤进行:1. 创建头结点2. 将头结点的前指针和后指针均指向自身,完成循环链接的闭合3. 将头结点作为链表的起始节点2.2 链表的遍历链表的遍历是指按照某种顺序遍历链表中的所有节点。
可以使用循环或递归的方法进行遍历,其具体步骤如下:1. 先将指针指向链表的起始节点2. 依次访问每个节点,并将指针指向下一个节点,直到指针指向空节点为止2.3 链表的插入链表的插入是指将一个新的节点插入到链表中的某个位置。
如果要在第i个位置插入一个新节点,需要进行以下操作:1. 新建一个节点,并将要插入的数据存储在其中2. 找到第i-1个节点,并将它的后指针指向新节点3. 将新节点的前指针指向第i-1个节点,后指针指向第i个节点4. 如果插入位置是链表的末尾,则需要将新节点的后指针指向头结点,完成循环链接的闭合2.4 链表的删除链表的删除是指将链表中某个节点删除。
如果要删除第i个节点,需要进行以下操作:1. 找到第i个节点2. 将第i-1个节点的后指针指向第i+1个节点3. 将第i+1个节点的前指针指向第i-1个节点4. 释放第i个节点所占用的内存空间3. 链表的应用链表常常被用于各种算法和数据结构中,如栈、队列、哈希表、图等。
链表具有无需预先分配内存空间,插入和删除操作效率高等优点,在某些场合可以取代数组进行操作。
4. 链表的优化在实际使用中,链表的优化也是非常重要的,可以采用以下方法进行优化:1. 在插入和删除操作频繁的场合,可以选用跳表、B树等数据结构进行优化2. 在查询操作频繁的场合,可以选用哈希表等数据结构进行优化3. 可以使用链表的迭代器进行遍历操作,比单纯使用指针更加方便和安全5. 总结带头结点的双向循环链表是一种常用的数据结构,具有插入和删除操作效率高、可以减少分配内存空间等优点。
双向循环链表中结点的交换
双向循环链表中结点的交换
双向循环链表是一种常见的数据结构,其中每个结点都有前驱和后继指针,可以实现快速的插入和删除操作。
在某些情况下,需要对双向循环链表中的结点进行交换操作,例如将两个相邻的结点位置互换。
下面介绍一种简单的方法来实现双向循环链表中结点的交换。
假设双向循环链表中有结点A、B、C、D,它们的前驱和后继指针分别为prev和next。
要将结点B和结点C进行交换操作,可以按照以下步骤进行:
1. 将结点B的前驱指针指向结点C的前驱结点A,将结点B的后继指针指向结点C的后继结点D,将结点C的前驱指针指向结点B,将结点C的后继指针指向结点B。
2. 将结点B的前驱结点A的后继指针指向结点C,将结点D的前驱指针指向结点B。
完成以上两个步骤后,双向循环链表中结点B和结点C的位置就会互换,同时它们的前驱和后继指针也会相应地更新。
这种方法比较简单,但需要注意一些细节,例如交换的结点不能是链表的头结点或尾结点,否则需要进行额外的处理。
- 1 -。
循环双链表的判空条件
循环双链表的判空条件循环双链表(Circular Doubly Linked List)是双向链表(Doubly Linked List)的一种特殊形式,其最后一个结点的 next 指向头结点,头结点的 prev 指向最后一个结点,从而形成了闭环。
循环双链表具有双向遍历的特性,可以实现快速插入、删除等操作,因此被广泛应用于数据结构和算法中。
在使用循环双链表时,判空条件是非常重要的,它决定了程序是否能够正常运行。
判空条件通常是根据链表的头结点来判断的,因为头结点是循环双链表的入口,它包含了链表的长度、头尾结点等信息。
不同的编程语言和应用场景可能会有不同的判空条件,下面给出几种常见的判空条件及其实现方式。
1. 头结点为空头结点为空是最常见的循环双链表判空条件,它表示整个链表为空。
在实现循环双链表时,通常会初始化一个头结点,并使其指向自己,也就是构成一个至少包含一个结点的循环双链表。
这样,在判空时只需要判断头结点的next 指针是否指向自己即可。
C++ 代码实现:``` template<typename T> class CircularDoublyLinkedList { private: struct Node { T data; Node *prev, *next;Node(const T& x = T(), Node* p = nullptr, Node* n = nullptr) : data(x), prev(p), next(n) {} };Node *head;public: CircularDoublyLinkedList() :head(new Node()) { head->prev = head->next = head; }bool empty() const { returnhead->next == head; } }; ```2. 结点数量为零结点数量为零是另一种常见的循环双链表判空条件,它表示链表中没有任何结点。
循环链表和双向链表
b.head->next = NULL; //此时,b中已只剩第一个结点(头), 为其置空表标志
return k; //返回结果链表中的元素个数
}
为了进一步说明上述程序,举一个程序运行的例子, 其各次循环的运行结果如图5-6所示
p
7 0 3 2 -9 3 1 5
^
(a)A(x)=p5(x)=7+3x2-9x3+x5,进入循环前
该程序不断比较A链和B链中的一对结点的指数值 (称其为当前结点)。开始时A链和B链中参加比较
的当前结点都是它们的第一个元素。
主循环while结束后,可能出现下列3种情况:①A
链和B链同时被处理完;②只有B链处理完;③只有A
链处理完。 对第一和第二种情况,不需要“善后”处理。对第 三种情况,B链中尚有未被处理完的结点,需将其挂 接在结果链的尾部。循环外的“if(q 不为空)将q
p = p->next; } // if (x==0) … else … q0 = q; q = q->next; delete q0; //将q所指结点从表中删除并释放,令q新指向原所 指的下一个 } // if (p->exp > q->exp ) … else … } //while if (q!=NULL) p0->next = q;
为处理方便,在具体存储多项式时,我们规定:
所存储的多项式已约简,即已合并同类项,不 保留0系数项,各项按指数的升序排列。 (二)多项式加法实现—直接操作链表 为操作方便,我采用带头结点的非循环链表,下面给 出一个例子说明多项式的这种表示法。
设有一个一元5次多项式: P5(x)=7+3x-9x3+x5
数据结构与算法(C语言篇)第2章 习题答案[2页]
习题答案1.填空题(1)线性(2)顺序表(3)单链表(4)数据域、指针域(5)头结点(6)一定(7)不一定2.思考题(1)线性表采用顺序存储通常被称为顺序表。
顺序表指的是集合中数据元素之间的逻辑结构为线性结构,并且数据元素按照逻辑顺序依次存放在地址连续的存储单元中。
一般情况下,线性表中的所有数据结点的类型是相同的。
在C语言中,通常使用一维数组和结构体来表示顺序表。
(2)线性表采用链式存储通常被称为单链表。
单链表指的是集合中数据元素之间的逻辑结构为线性结构,但是数据元素所在的存储单元在内存地址上是不连续的。
单链表中的结点都是由两部分组成,一部分为数据域(data);另一部分为指针域(next)。
简单地说,data域用来存放结点的数据,而next域存放的是一个指针,该指针保存的是下一个结点所在的内存地址,或者说该指针指向下一个结点。
(3)在单链表中,如果需要查找某一个结点的后继时,直接通过指针移动到下一个结点即可。
但是要查找某一结点的前驱时,则需要从结点头开始。
为了提高数据操作的效率,引入双向循环链表。
双向循环链表中结点的结构与单链表不同,每一个结点都有一个指向前一个结点的指针和一个指向后一个结点的指针。
4.编程题(1)int seqlist_insert(seqlist_t *l, int value){if(seqlist_full(l)){ //判断是否为满printf("seqlist full\n");return -1;}l->last++; //数组下标加1,表示要插入数据l->data[l->last] = value; //将需要插入的数据赋值到数组中,表示插入数据 return 0;}(2)int linklist_head_insert(linklist_t *h, datatype_t value){linklist_t *temp;//为新插入的数据结点申请空间temp = (linklist_t *)malloc(sizeof(linklist_t));temp->data = value; //为新插入结点的数据域赋值数据temp->next = h->next; //将头结点指针指向的下一个结点的地址赋值给新结点的指针 h->next = temp; //将头结点指针指向新的结点return 0;}(3)void dlinklist_insert(dlinklist_t *dl, datatype_t value){//使用malloc函数为新插入的结点申请空间dlinklist_t *temp = (dlinklist_t *)malloc(sizeof(dlinklist_t));//为新插入的结点赋值temp->data = value;//获取第一个有数据的结点的地址,地址为dl->next//如果此时只有一个头结点,则假设存在有数据的结点dlinklist_t *pnext = dl->next;//将头结点与新插入的结点建立关系dl->next = temp;temp->prior = dl;//将头结点的下一个结点与新插入的结点建立关系temp->next = pnext;pnext->prior = temp;return ;}(4)使用递归的方法,函数调用自己本身,形成一个函数的复用//参数为指向头结点的指针int show_reverse_linklist(linklist_t *h){if(h->next == NULL){printf(“%d ”, h->data);return 0;}show_reverse_linklist(h->next);printf(“%d ”, h->data);return 0;}。
C语言版数据结构知识点汇总
C语言版数据结构知识点汇总C语言是一种强大的编程语言,广泛应用于数据结构与算法的实现。
掌握C语言版数据结构的知识可以帮助开发人员更好地理解和设计高效的程序。
下面是C语言版数据结构的一些重要知识点的汇总:1. 数组(Array):数组是一种基本的数据结构,用于存储一系列相同类型的元素。
在C语言中,数组是通过下标来访问元素的,数组下标从0开始计数。
2. 链表(Linked List):链表是一种动态数据结构,不需要连续的内存空间。
链表由一系列结点组成,每个结点包含数据和指向下一个结点的指针。
常见的链表有单向链表、双向链表和循环链表。
3. 栈(Stack):栈是一种先进后出(LIFO)的数据结构,只能在末尾进行插入和删除操作。
在C语言中,栈可以用数组或链表来实现。
栈常用于表达式求值、函数调用和递归等场景。
4. 队列(Queue):队列是一种先进先出(FIFO)的数据结构,只能在一端进行插入操作,另一端进行删除操作。
在C语言中,队列可以用数组或链表来实现。
队列常用于广度优先和任务调度等场景。
5. 树(Tree):树是一种非线性的数据结构,由一系列的结点组成,每个结点可以有多个子结点。
树的一些重要特点包括根结点、父结点、子结点、叶子结点和深度等。
常见的树结构有二叉树和二叉树。
6. 图(Graph):图是一种非线性的数据结构,由一组顶点和一组边组成。
图的一些重要概念包括顶点的度、路径、连通性和环等。
图有多种表示方法,包括邻接矩阵和邻接表。
7.查找算法:查找算法用于在数据集中查找特定元素或确定元素是否存在。
常见的查找算法有顺序查找、二分查找和哈希查找。
在C语言中,可以使用数组、链表和树来实现不同的查找算法。
8.排序算法:排序算法用于将数据集中的元素按照特定的顺序进行排列。
常见的排序算法有冒泡排序、插入排序、选择排序、快速排序和归并排序等。
排序算法的选择取决于数据规模、时间复杂度和稳定性等因素。
9. 堆(Heap):堆是一种特殊的树结构,具有如下特点:完全二叉树、最大堆或最小堆的性质。
C语言实现循环链表
C语⾔实现循环链表本⽂实例为⼤家分享了C语⾔实现循环链表的具体代码,供⼤家参考,具体内容如下注意事项:1、循环链表设置尾指针。
由于在链表的操作过程中,尾指针会不断变化,所以在⼀些函数的形参中都设置指向头指针的指针。
以及链表的结束判断条件变成q是否等于尾指针。
2、注意传递的实参需要取地址3、循环链表的优势在于双链表合并,以及实现尾插法简单(⾸先新建结点指向头结点,然后把尾指针的next域指向该新建结点)4、在创建链表时,使⽤尾插法,⽽不是⽤头插法(因为头插法很难去更新尾指针,使得最后尾指针还需额外更新⼀次),直接⽤头插法建⽴的是头指针,⽽⾮尾指针代码:#include<stdio.h>#include<stdlib.h>typedef struct Node{int data;struct Node * next;}Node, *LinkList;LinkList Creat();void Destroy(LinkList *L);void Insert(LinkList *L, int val, int index);void Delete(LinkList *L, int index);void Traverse(LinkList L);int main(){LinkList L = Creat();Traverse(L);Insert(&L, 1, 5);printf("After inserting is :\n");Traverse(L);printf("After deleting is :\n");Delete(&L, 2);Traverse(L);Destroy(&L);Traverse(L);}LinkList Creat(){LinkList L = (LinkList)malloc(sizeof(Node));//⽤L指针指向新建结点,这⾥L还不算尾指针int n;L->data = -1;L->next = L;//头结点的指针域指向头结点, 注意!这⾥是对尾指针的初始化。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
双向循环链表:
#include<stdio.h>
typedef int elemtype;
typedef struct dupnode
{elemtype data;
struct dupnode *next,*prior;
} dulinklist;
dulinklist *creatlist()
{char ch;int x;
dulinklist *head,*r,*p;
p=(dulinklist*)malloc(sizeof(dulinklist)); head=p;
p->next=head;
p->prior=p;
r=p;
ch=getchar();
while(ch!='?')
{scanf("%d",&x);
p=(dulinklist*)malloc(sizeof(dulinklist));
p->data=x;
p->prior=r;
p->next=head;
r->next=p;
吗r=r->next;
printf("%d,%x,%x\n",x,p->prior->next,p->prior->prior);
ch=getchar();
}
return(head);
}
void main()
{creatlist();
}
#include<stdio.h>
#include<stdlib.h>
#include<iostream>
using namespace std;
int n;
typedef struct node
{
int data;
struct node *prior;
struct node *next;
}node,*DoubleLinkList;
void Creat_List(DoubleLinkList L) {
DoubleLinkList r,s;
cout<<"请输入n的值"<<endl;
cin>>n;
s = L;
s->prior = s;
s->data = n;
for(int i=0;i<n;i++)
{
r = (DoubleLinkList)malloc(sizeof(node)); L->next = r;
r->next = s->next;
r->prior = L;
s->next->prior = r;
r->data = i;
L = r;
}
}
void Desplay_List(DoubleLinkList L)
{
DoubleLinkList p;
p = L->next;
for(int i=0;i<n;i++)
{
cout<<"输出:"<<p->data<<endl; p = p->next;
}
}
void Destroy_List(DoubleLinkList L) {
DoubleLinkList p;
p = L;
node *temp;
for(int k=0;k<n;k++)
{
p = L->next;
temp = p->next;
temp->prior->next = temp->next; temp->next->prior = temp->prior; free(temp);
}
cout<<"空间释放成功"<<endl;
}
void main()
{
node a;
DoubleLinkList p;
p = &a;
Creat_List(p);
Desplay_List(p);
Destroy_List(p);
}
#include <stdio.h>
#include <stdlib.h>
typedef struct node
{
int data;
struct node *pri; //前驱
struct node *next; //后驱
}List;
bool Insert(List *list, int index, int value) {
//查找要插入的位置的前一个
int i = 0;
while( list && i < (index-1) )
{
list = list->next;
i++;
}
if( list==NULL || i > (index-1) )
{
printf("插入位置不正确, insert failed");
return false;
}
node* new_node = (node*)malloc(sizeof(node)); if(new_node == NULL)
{
printf("malloc new node memery fail\n");
return false;
}
new_node->data = value;
new_node->pri = list;
new_node->next = list->next;
list->next = new_node;
list->next->pri = new_node;
return true;
}
bool DelNote(List *list, int index)
{
//查找要插入的位置的前一个
int i = 0;
while( list && i < (index-1) )
{
list = list->next;
i++;
}
if( list==NULL || i > (index-1) )
{
printf("删除位置不正确, insert failed");
return false;
}
node* p = list->next;
list->next = list->next->next;
list->next->pri = list;
printf("delete node value:%d \n",p->data); free(p);
return true;
}
void Print(List *list)
{
if(list->next == NULL)
{
printf("list is empty!\n"); return ;
}
while(list->next)
{
list = list->next;
printf("%d ", list->data); }
}
int main()
{
List list;
//构建头结点
list.data = 0;
list.next = NULL;
list.pri = NULL;
// Print(&list);
int i = 1;
bool flag = false;
while(i<10)
{
flag =Insert(&list, i, i);
if(!flag)
{
printf("insert failed!!\n");
}
i++;
}
Print(&list);
printf("enter delete node index \n");
int index;
scanf("%d", &index);
flag = DelNote(&list, index);
if(flag)
printf("delete note success!!\n"); Print(&list);
return 0;
}。