http://blog.csdn.net/fisherwan/article/details/19754585

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

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

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

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

[cpp] view plain copy
  1. #ifndef ONE_WAY_CIRCULAR_LINK_LIST_H
  2. #define ONE_WAY_CIRCULAR_LINK_LIST_H
  3. typedef struct Node
  4. {
  5. int data;
  6. struct Node *pNext;
  7. }NODE, *pNODE;
  8. //创建单向循环链表
  9. pNODE CreateSgCcLinkList(void);
  10. //打印链表
  11. void TraverseSgCcLinkList(pNODE pHead);
  12. //判断链表是否为空
  13. int IsEmptySgCcLinkList(pNODE pHead);
  14. //计算链表的长度
  15. int GetLengthSgCcLinkList(pNODE pHead);
  16. //向链表中插入节点
  17. int InsertEleSgCcLinkList(pNODE pHead, int pos, int data);
  18. //从链表中删除节点
  19. int DeleteEleSgCcLinkList(pNODE pHead, int pos);
  20. //删除整个链表,释放内存
  21. void FreeMemory(pNODE *ppHead);
  22. #endif

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

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

[cpp] view plain copy
  1. p_new->pNext = pHead;    //这里一定是pHead,因为最后一个节点总是指着头节点

它的意思就是没创建一个节点,让这个节点指向头节点,然后就形成了一个环,也就成了循环链表。

[cpp] view plain copy
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include "SgCcLinkLIst.h"
  4. //创建单向循环链表
  5. pNODE CreateSgCcLinkList(void)
  6. {
  7. int i, length = 0, data = 0;
  8. pNODE pTail = NULL, p_new = NULL;
  9. pNODE pHead = (pNODE)malloc(sizeof(NODE));
  10. if (NULL == pHead)
  11. {
  12. printf("内存分配失败!\n");
  13. exit(EXIT_FAILURE);
  14. }
  15. pHead->data = 0;
  16. pHead->pNext = pHead;
  17. pTail = pHead;
  18. printf("请输入要创建链表的长度:");
  19. scanf("%d", &length);
  20. for (i=1; i<length+1; i++)
  21. {
  22. p_new = (pNODE)malloc(sizeof(NODE));
  23. if (NULL == p_new)
  24. {
  25. printf("内存分配失败!\n");
  26. exit(EXIT_FAILURE);
  27. }
  28. printf("请输入第%d个节点的元素值:", i);
  29. scanf("%d", &data);
  30. p_new->data = data;
  31. p_new->pNext = pHead;    //这里一定是pHead,因为最后一个节点总是指着头节点
  32. pTail->pNext = p_new;
  33. pTail = p_new;
  34. }
  35. return pHead;
  36. }

(2)这部分是获得链表的相关信息,和单向链表一样,头节点不参与运算;但是和单向链表不同的地方就是判断的时候是和头结点进行比较,如何相等的话呢,说明到了链表的结尾。

[cpp] view plain copy
  1. //打印链表
  2. void TraverseSgCcLinkList(pNODE pHead)
  3. {
  4. pNODE pt = pHead->pNext;
  5. printf("链表打印如:");
  6. while (pt != pHead)
  7. {
  8. printf("%d ", pt->data);
  9. pt = pt->pNext;
  10. }
  11. putchar('\n');
  12. }
  13. //判断链表是否为空
  14. int IsEmptySgCcLinkList(pNODE pHead)
  15. {
  16. if (pHead->pNext == pHead)
  17. return 1;
  18. else
  19. return 0;
  20. }
  21. //计算链表长度
  22. int GetLengthSgCcLinkList(pNODE pHead)
  23. {
  24. int length = 0;
  25. pNODE pt = pHead->pNext;
  26. while (pt != pHead)
  27. {
  28. length++;
  29. pt = pt->pNext;
  30. }
  31. return length;
  32. }

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

[cpp] view plain copy
  1. //向链表中插入节点
  2. int InsertEleSgCcLinkList(pNODE pHead, int pos, int data)
  3. {
  4. pNODE p_new = NULL;
  5. if (pos > 0 && pos < GetLengthSgCcLinkList(pHead) + 2)
  6. {
  7. p_new = (pNODE)malloc(sizeof(NODE));
  8. if (NULL == <span style="font-family: Arial, Helvetica, sans-serif;">p_new </span><span style="font-family: Arial, Helvetica, sans-serif;">)</span>
  9. {
  10. printf("内存分配失败!\n");
  11. exit(EXIT_FAILURE);
  12. }
  13. while (1)
  14. {
  15. pos--;
  16. if (0 == pos)
  17. break;
  18. pHead = pHead->pNext;
  19. }
  20. p_new->data = data;
  21. p_new->pNext = pHead->pNext;
  22. pHead->pNext = p_new;
  23. return 1;
  24. }
  25. else
  26. return 0;
  27. }
[cpp] view plain copy
  1. <span style="font-family: Arial, Helvetica, sans-serif;">//从链表中删除节点</span>
[cpp] view plain copy
  1. int DeleteEleSgCcLinkList(pNODE pHead, int pos)
  2. {
  3. pNODE pt = NULL;
  4. if (pos > 0 && pos < GetLengthSgCcLinkList(pHead) + 1)
  5. {
  6. while (1)
  7. {
  8. pos--;
  9. if (0 == pos)
  10. break;
  11. pHead = pHead->pNext;
  12. }
  13. pt = pHead->pNext->pNext;
  14. free(pHead->pNext);
  15. pHead->pNext = pt;
  16. return 1;
  17. }
  18. else
  19. return 0;
  20. }

(4)这部分是释放内存,和单向链表有些不一样,因为单向循环链表是个环,最后只剩下头节点的时候要单独处理,这个受我判断条件的限制。当然可能有更好的方法,我们可以共同讨论。这里我分了两种情况来释放内存。

[cpp] view plain copy
  1. //删除整个链表,释放内存
  2. void FreeMemory(pNODE *ppHead)
  3. {
  4. pNODE pt = NULL;
  5. while (*ppHead != NULL)
  6. {
  7. if (*ppHead == (*ppHead)->pNext) //如果只有头节点一个
  8. {
  9. free(*ppHead);
  10. *ppHead = NULL;
  11. }
  12. else                    //如果不止头节点一个
  13. {
  14. pt = (*ppHead)->pNext->pNext;
  15. free((*ppHead)->pNext);
  16. (*ppHead)->pNext = pt;
  17. }
  18. }
  19. }

main.cpp 测试程序源文件——这个程序通过一些简单的交互用来测试各个函数是否实现了各自的功能。

[cpp] view plain copy
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include "SgCcLinkList.h"
  4. int main(void)
  5. {
  6. int flag = 0, length = 0;
  7. int position = 0, value = 0;
  8. pNODE head = NULL;
  9. head = CreateSgCcLinkList();
  10. flag = IsEmptySgCcLinkList(head);
  11. if (flag)
  12. printf("单向循环链表为空!\n");
  13. else
  14. {
  15. length = GetLengthSgCcLinkList(head);
  16. printf("单向循环链表的长度为:%d\n", length);
  17. TraverseSgCcLinkList(head);
  18. }
  19. printf("请输入要插入节点的位置和元素值(两个数用空格隔开):");
  20. scanf("%d %d", &position, &value);
  21. flag = InsertEleSgCcLinkList(head, position, value);
  22. if (flag)
  23. {
  24. printf("插入节点成功!\n");
  25. TraverseSgCcLinkList(head);
  26. }
  27. else
  28. printf("插入节点失败!\n");
  29. flag = IsEmptySgCcLinkList(head);
  30. if (flag)
  31. printf("单向循环链表为空,不能进行删除操作!\n");
  32. else
  33. {
  34. printf("请输入要删除节点的位置:");
  35. scanf("%d", &position);
  36. flag = DeleteEleSgCcLinkList(head, position);
  37. if (flag)
  38. {
  39. printf("删除节点成功!\n");
  40. TraverseSgCcLinkList(head);
  41. }
  42. else
  43. printf("删除节点失败!\n");
  44. }
  45. FreeMemory(&head);
  46. if (NULL == head)
  47. printf("已成功删除单向循环链表,释放内存完成!\n");
  48. else
  49. printf("删除单向循环链表失败,释放内存未完成!\n");
  50. return 0;
  51. }

PS:数据结构的学习还在继续,刚开始写这个程序的时候,在释放内存的时候碰到了一些问题,不过后面通过调试还是解决了。所以,我想说调试能力也是很重要的,因为调试过一篇,你对这个程序的原理也懂的差不多了。如果你们在看程序的时候发现错误,希望能积极指出来。

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

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

  1. (C语言版)链表(三)——实现双向链表创建、删除、插入、释放内存等简单操作

    http://blog.csdn.net/fisherwan/article/details/19760681 上午写了下单向循环链表的程序,今天下午我把双向链表的程序写完了.其实双向链表和单向链表也 ...

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

    http://blog.csdn.net/fisherwan/article/details/19801993 双向循环链表是基于双向链表的基础上实现的,和双向链表的操作差不多,唯一的区别就是它是个循 ...

  3. C语言之链表探究之单向链表(List)、附双向循环链表参考博文地址

    参考博文:C语言数据结构-创建链表的四种方法 链表结构图一 链表结构图二 链表结构图三 链表结构图四 一.静态链表 例1: 附例1代码: #include <stdio.h>typedef ...

  4. python遍历链表_Python实现单向循环链表

    insert方法,在中部插入时候与单向链表一样,头部和尾部插入的方法已经写了add和append,不必再重写,继续写search和delete方法,代码如下; def insert(self,i,it ...

  5. 《数据结构》C语言版 链表的基本操作实现

    #include <stdio.h> #include <stdlib.h>#define ok 1 #define error -1typedef int ElemType; ...

  6. 链表(创建,插入,删除和打印输出

    http://www.bianceng.cn/Programming/C/200705/327.htm  (以下不全,去此网址看) 数组作为存放同类数据的集合,给我们在程序设计时带来很多的方便,增加了 ...

  7. 二叉搜索树的创建以及删除

    #include <stdio.h> #include <stdlib.h> #define EOR -1typedef int EleType;//typedef 定义存放数 ...

  8. c语言用链表对学生成绩排序,学生成绩排序和平均分计算利用c语言链表的创建插入删除.doc...

    #define NULL 0 #define LEN sizeof(struct student) struct student { long num; float score; struct stu ...

  9. 二叉搜索树(创建,插入,删除):基础篇,适合新手观看。

    1.1 二叉搜索树的插入 二叉搜索树的概念相信大家都很清楚,无非就是左小右大 创建二叉搜索树,其实就是多次调用二叉搜索树的插入方法,所以首先我们来讲讲如何插入节点到二叉搜索树里,假设一颗二叉搜索树如下 ...

最新文章

  1. 下一个更大元素 I(LeetCode 496)
  2. vue mui html不解析,记下Vue中使用Mui.js踩到的坑
  3. Rust+Yew之hello world
  4. 【多题合集】线段覆盖1、2、3
  5. Spring的注解问题
  6. access子窗体的控件vba怎么写_第37讲:VBA代码中运行错误的处理方式
  7. bzoj 3672 利用点分治将CDQ分治推广到树型结构上
  8. 单片机常用的14个C语言算法,看过的都成了大神!
  9. 西工大机考《概率论与数理统计》大作业网考
  10. 全面了解APON,BPON,EPON,GPON
  11. iOS 逆向编程(二)越狱入门知识
  12. 江苏省秋c语言二级用什么软件,在哪里可以查到江苏省计算机c语言二级考试资料?...
  13. cookie 、localStorage 和 sessionStorage 区别
  14. 一段很有意思的代码!!
  15. 川大计算机学院周激流,周激流(电子信息学院)老师 - 四川大学 - 院校大全
  16. 求助:tp-link wr720n路由器,想刷打印服务器!
  17. windows 平台使用dul 抽取Linux oracle ASM 磁盘数据文件
  18. android和rtos相互切换,通用操作系统与实时操作系统(RTOS)比较
  19. Java程序员:真是会服了面试官,不就要个40k嘛硬是把Spring问烂
  20. 技术项目的评审及其标准

热门文章

  1. mysql联合索引与Where子句优化浅析
  2. javascript数据结构-栈
  3. 夺命雷公狗---ECSHOP---08---商品页的拇改成星星
  4. (接口)银联证书上传被修改的问题和读取证书的绝对路径问题
  5. [Json] C#ConvertJson|List转成Json|对象|集合|DataSet|DataTable|DataReader转成Json (转载)...
  6. html5中折叠面板,Ant Design中折叠面板Collapse
  7. python中英文字符和中文字符存储长度不同_Django如何正确截取中英混合字符串及表单中限制中文字符中长度...
  8. c语言清空输入缓冲区函数,c语言:C语言清空输入缓冲区在标准输入(stdin)情况 -电脑资料...
  9. python实现词语相似度计算分析_相似度计算的方法及Python实现
  10. php-cgi cpu很高,php-cgi占用cpu资源过高的解决方法