1000字范文,内容丰富有趣,学习的好帮手!
1000字范文 > (C语言版)链表(二)——实现单向循环链表创建 插入 删除 释放内存等简单操作

(C语言版)链表(二)——实现单向循环链表创建 插入 删除 释放内存等简单操作

时间:2023-10-07 19:34:11

相关推荐

(C语言版)链表(二)——实现单向循环链表创建 插入 删除 释放内存等简单操作

/fisherwan/article/details/19754585

昨天写了单向链表的代码,今天上午把单向循环链表的程序给敲完了。链表的相关操作一样的,包含链表的创建、判断链表是否为空、计算链表长度、向链表中插入节点、从链表中删除节点、删除整个链表释放内存。如果单向链表理解了,那单向循环链表也就不难了。

单向循环链表如下图所示:

看图可以知道,单向循环链表和单向链表差不多,只不过是最后的尾节点指向的不是空,而是指向头节点。理解这一点很重要,因为这是我们写程序的关键。下面我们上代码:

SqCcLinkList.h 头文件——定义了节点结构体,以及相关操作的函数声明。

[cpp]view plaincopy#ifndefONE_WAY_CIRCULAR_LINK_LIST_H #defineONE_WAY_CIRCULAR_LINK_LIST_H typedefstructNode { intdata; structNode*pNext; }NODE,*pNODE; //创建单向循环链表 pNODECreateSgCcLinkList(void); //打印链表 voidTraverseSgCcLinkList(pNODEpHead); //判断链表是否为空 intIsEmptySgCcLinkList(pNODEpHead); //计算链表的长度 intGetLengthSgCcLinkList(pNODEpHead); //向链表中插入节点 intInsertEleSgCcLinkList(pNODEpHead,intpos,intdata); //从链表中删除节点 intDeleteEleSgCcLinkList(pNODEpHead,intpos); //删除整个链表,释放内存 voidFreeMemory(pNODE*ppHead); #endif

SqCcLinkList.cpp 链表源文件——这里包含了各种相关操作的函数的定义。

(1)这部分是创建链表,和单向链表一样,一开始也是创建了一个头节点,初始化时,头结点的指针指向自己(这是和单向链表不一样的地方)。在写程序时,主要体现在下面的一行代码:

[cpp]view plaincopyp_new->pNext=pHead;//这里一定是pHead,因为最后一个节点总是指着头节点 它的意思就是没创建一个节点,让这个节点指向头节点,然后就形成了一个环,也就成了循环链表。 [cpp]view plaincopy#include<stdio.h> #include<stdlib.h> #include"SgCcLinkLIst.h" //创建单向循环链表 pNODECreateSgCcLinkList(void) { inti,length=0,data=0; pNODEpTail=NULL,p_new=NULL; pNODEpHead=(pNODE)malloc(sizeof(NODE)); if(NULL==pHead) { printf("内存分配失败!\n"); exit(EXIT_FAILURE); } pHead->data=0; pHead->pNext=pHead; pTail=pHead; printf("请输入要创建链表的长度:"); scanf("%d",&length); for(i=1;i<length+1;i++) { p_new=(pNODE)malloc(sizeof(NODE)); if(NULL==p_new) { printf("内存分配失败!\n"); exit(EXIT_FAILURE); } printf("请输入第%d个节点的元素值:",i); scanf("%d",&data); p_new->data=data; p_new->pNext=pHead;//这里一定是pHead,因为最后一个节点总是指着头节点 pTail->pNext=p_new; pTail=p_new; } returnpHead; } (2)这部分是获得链表的相关信息,和单向链表一样,头节点不参与运算;但是和单向链表不同的地方就是判断的时候是和头结点进行比较,如何相等的话呢,说明到了链表的结尾。 [cpp]view plaincopy//打印链表 voidTraverseSgCcLinkList(pNODEpHead) { pNODEpt=pHead->pNext; printf("链表打印如:"); while(pt!=pHead) { printf("%d",pt->data); pt=pt->pNext; } putchar('\n'); } //判断链表是否为空 intIsEmptySgCcLinkList(pNODEpHead) { if(pHead->pNext==pHead) return1; else return0; } //计算链表长度 intGetLengthSgCcLinkList(pNODEpHead) { intlength=0; pNODEpt=pHead->pNext; while(pt!=pHead) { length++; pt=pt->pNext; } returnlength; }

(3)这部分是链表的插入和删除操作,和单向链表一样。

[cpp]view plaincopy//向链表中插入节点 intInsertEleSgCcLinkList(pNODEpHead,intpos,intdata) { pNODEp_new=NULL; if(pos>0&&pos<GetLengthSgCcLinkList(pHead)+2) { p_new=(pNODE)malloc(sizeof(NODE)); if(NULL==<spanstyle="font-family:Arial,Helvetica,sans-serif;">p_new</span><spanstyle="font-family:Arial,Helvetica,sans-serif;">)</span> { printf("内存分配失败!\n"); exit(EXIT_FAILURE); } while(1) { pos--; if(0==pos) break; pHead=pHead->pNext; } p_new->data=data; p_new->pNext=pHead->pNext; pHead->pNext=p_new; return1; } else return0; }[cpp]view plaincopy<spanstyle="font-family:Arial,Helvetica,sans-serif;">//从链表中删除节点</span>[cpp]view plaincopyintDeleteEleSgCcLinkList(pNODEpHead,intpos) { pNODEpt=NULL; if(pos>0&&pos<GetLengthSgCcLinkList(pHead)+1) { while(1) { pos--; if(0==pos) break; pHead=pHead->pNext; } pt=pHead->pNext->pNext; free(pHead->pNext); pHead->pNext=pt; return1; } else return0; } (4)这部分是释放内存,和单向链表有些不一样,因为单向循环链表是个环,最后只剩下头节点的时候要单独处理,这个受我判断条件的限制。当然可能有更好的方法,我们可以共同讨论。这里我分了两种情况来释放内存。

[cpp]view plaincopy//删除整个链表,释放内存 voidFreeMemory(pNODE*ppHead) { pNODEpt=NULL; while(*ppHead!=NULL) { if(*ppHead==(*ppHead)->pNext)//如果只有头节点一个 { free(*ppHead); *ppHead=NULL; } else//如果不止头节点一个 { pt=(*ppHead)->pNext->pNext; free((*ppHead)->pNext); (*ppHead)->pNext=pt; } } }

main.cpp 测试程序源文件——这个程序通过一些简单的交互用来测试各个函数是否实现了各自的功能。 [cpp]view plaincopy#include<stdio.h> #include<stdlib.h> #include"SgCcLinkList.h" intmain(void) { intflag=0,length=0; intposition=0,value=0; pNODEhead=NULL; head=CreateSgCcLinkList(); flag=IsEmptySgCcLinkList(head); if(flag) printf("单向循环链表为空!\n"); else { length=GetLengthSgCcLinkList(head); printf("单向循环链表的长度为:%d\n",length); TraverseSgCcLinkList(head); } printf("请输入要插入节点的位置和元素值(两个数用空格隔开):"); scanf("%d%d",&position,&value); flag=InsertEleSgCcLinkList(head,position,value); if(flag) { printf("插入节点成功!\n"); TraverseSgCcLinkList(head); } else printf("插入节点失败!\n"); flag=IsEmptySgCcLinkList(head); if(flag) printf("单向循环链表为空,不能进行删除操作!\n"); else { printf("请输入要删除节点的位置:"); scanf("%d",&position); flag=DeleteEleSgCcLinkList(head,position); if(flag) { printf("删除节点成功!\n"); TraverseSgCcLinkList(head); } else printf("删除节点失败!\n"); } FreeMemory(&head); if(NULL==head) printf("已成功删除单向循环链表,释放内存完成!\n"); else printf("删除单向循环链表失败,释放内存未完成!\n"); return0; } PS:数据结构的学习还在继续,刚开始写这个程序的时候,在释放内存的时候碰到了一些问题,不过后面通过调试还是解决了。所以,我想说调试能力也是很重要的,因为调试过一篇,你对这个程序的原理也懂的差不多了。如果你们在看程序的时候发现错误,希望能积极指出来。

下一站是双向链表。加油吧!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。