Linux c 算法与数据结构--双向链表

链表是linux c中非常重要的数据结构,双向链表与单向链表的区别,是它每个节点有两个指针域,分别指向该节点的前一个节点与后一个节点;

而链表的操作主要是查询、插入、删除、遍历等,下面来看一个双向链表,主要是进行写小练习,加深印象!

代码如下:

Dlist.h

[cpp] view plaincopy
  1. #ifndef DList_H  
  2. #define DList_H  
  3. typedef  int Item;  
  4. typedef struct Node * PNode;  
  5. typedef PNode Position;  
  6. /*定义节点类型*/  
  7. typedef struct Node  
  8. {  
  9.     Item data;        /*数据域*/  
  10.     PNode previous; /*指向前驱*/  
  11.     PNode next;        /*指向后继*/  
  12. }Node;  
  13. /*定义链表类型*/  
  14. typedef struct  
  15. {  
  16.     PNode head;        /*指向头节点*/  
  17.     PNode tail;        /*指向尾节点*/  
  18.     int size;  
  19. }DList;  
  20.   
  21. /*分配值为i的节点,并返回节点地址*/  
  22. Position MakeNode(Item i);  
  23.   
  24. /*释放p所指的节点*/  
  25. void FreeNode(PNode p);  
  26.   
  27. /*构造一个空的双向链表*/  
  28. DList* InitList();  
  29.   
  30. /*摧毁一个双向链表*/  
  31. void DestroyList(DList *plist);  
  32.   
  33. /*将一个链表置为空表,释放原链表节点空间*/  
  34. void ClearList(DList *plist);  
  35.   
  36. /*返回头节点地址*/  
  37. Position GetHead(DList *plist);  
  38.   
  39. /*返回尾节点地址*/  
  40. Position GetTail(DList *plist);  
  41.   
  42. /*返回链表大小*/  
  43. int GetSize(DList *plist);  
  44.   
  45. /*返回p的直接后继位置*/  
  46. Position GetNext(Position p);  
  47.   
  48. /*返回p的直接前驱位置*/  
  49. Position GetPrevious(Position p);  
  50.   
  51. /*将pnode所指节点插入第一个节点之前*/  
  52. PNode InsFirst(DList *plist,PNode pnode);  
  53.   
  54. /*将链表第一个节点删除并返回其地址*/  
  55. PNode DelFirst(DList *plist);  
  56.   
  57. /*获得节点的数据项*/  
  58. Item GetItem(Position p);  
  59.   
  60. /*设置节点的数据项*/  
  61. void SetItem(Position p,Item i);  
  62.   
  63. /*删除链表中的尾节点并返回其地址,改变链表的尾指针指向新的尾节点*/  
  64. PNode Remove(DList *plist);  
  65.   
  66. /*在链表中p位置之前插入新节点S*/  
  67. PNode InsBefore(DList *plist,Position p,PNode s);  
  68.   
  69. /*在链表中p位置之后插入新节点s*/  
  70. PNode InsAfter(DList *plist,Position p,PNode s);  
  71.   
  72. /*返回在链表中第i个节点的位置*/  
  73. PNode LocatePos(DList *plist,int i);  
  74.   
  75. /*依次对链表中每个元素调用函数visit()*/  
  76. void ListTraverse(DList *plist,void (*visit)());  
  77. #endif  

DList.c  

[cpp] view plaincopy
  1. #include"DList.h"  
  2. #include<malloc.h>  
  3. #include<stdlib.h>  
  4. /*分配值为i的节点,并返回节点地址*/  
  5. Position MakeNode(Item i)  
  6. {  
  7.     PNode p = NULL;   
  8.     p = (PNode)malloc(sizeof(Node));  
  9.     if(p!=NULL)  
  10.     {  
  11.         p->data = i;  
  12.         p->previous = NULL;  
  13.         p->next = NULL;  
  14.     }      
  15.     return p;  
  16. }  
  17. /*释放p所指的节点*/  
  18. void FreeNode(PNode p)  
  19. {  
  20.      free(p);  
  21. }  
  22. /*构造一个空的双向链表*/  
  23. DList * InitList()  
  24. {  
  25.     DList *plist = (DList *)malloc(sizeof(DList));  
  26.     PNode head = MakeNode(0);   
  27.     if(plist!=NULL)  
  28.     {  
  29.         if(head!=NULL)  
  30.         {  
  31.             plist->head = head;  
  32.             plist->tail = head;  
  33.             plist->size = 0;  
  34.         }  
  35.         else  
  36.             return NULL;  
  37.     }  
  38.     return plist;  
  39. }  
  40.   
  41. /*摧毁一个双向链表*/  
  42. void DestroyList(DList *plist)  
  43. {  
  44.     ClearList(plist);  
  45.     free(GetHead(plist));  
  46.     free(plist);  
  47. }  
  48.   
  49. /*判断链表是否为空表*/  
  50. int IsEmpty(DList *plist)  
  51. {  
  52.     if(GetSize(plist)==0&&GetTail(plist)==GetHead(plist))  
  53.         return 1;  
  54.     else  
  55.         return 0;  
  56. }  
  57. /*将一个链表置为空表,释放原链表节点空间*/  
  58. void ClearList(DList *plist)  
  59. {  
  60.     PNode temp,p;  
  61.     p = GetTail(plist);  
  62.     while(!IsEmpty(plist))  
  63.     {      
  64.         temp = GetPrevious(p);  
  65.         FreeNode(p);  
  66.         p = temp;  
  67.         plist->tail = temp;  
  68.         plist->size--;  
  69.     }  
  70. }  
  71.   
  72. /*返回头节点地址*/  
  73. Position GetHead(DList *plist)  
  74. {  
  75.     return plist->head;  
  76. }  
  77.   
  78. /*返回尾节点地址*/  
  79. Position GetTail(DList *plist)  
  80. {  
  81.     return plist->tail;  
  82. }  
  83.   
  84. /*返回链表大小*/  
  85. int GetSize(DList *plist)  
  86. {  
  87.     return plist->size;  
  88. }  
  89.   
  90. /*返回p的直接后继位置*/  
  91. Position GetNext(Position p)  
  92. {  
  93.     return p->next;  
  94. }  
  95.   
  96. /*返回p的直接前驱位置*/  
  97. Position GetPrevious(Position p)  
  98. {  
  99.     return p->previous;  
  100. }  
  101.   
  102. /*将pnode所指节点插入第一个节点之前*/  
  103. PNode InsFirst(DList *plist,PNode pnode)  
  104. {  
  105.     Position head = GetHead(plist);  
  106.   
  107.     if(IsEmpty(plist))  
  108.         plist->tail = pnode;  
  109.     plist->size++;  
  110.   
  111.     pnode->next = head->next;  
  112.     pnode->previous = head;  
  113.   
  114.     if(head->next!=NULL)  
  115.         head->next->previous = pnode;  
  116.     head->next = pnode;  
  117.       
  118.     return pnode;   
  119. }  
  120.   
  121. /*将链表第一个节点删除,返回该节点的地址*/  
  122. PNode DelFirst(DList *plist)  
  123. {  
  124.     Position head = GetHead(plist);  
  125.     Position p=head->next;  
  126.     if(p!=NULL)  
  127.     {  
  128.         if(p==GetTail(plist))  
  129.             plist->tail = p->previous;  
  130.         head->next = p->next;  
  131.         head->next->previous = head;  
  132.         plist->size--;  
  133.           
  134.     }      
  135.     return p;  
  136. }  
  137.   
  138. /*获得节点的数据项*/  
  139. Item GetItem(Position p)  
  140. {  
  141.     return p->data;  
  142. }  
  143.   
  144. /*设置节点的数据项*/  
  145. void SetItem(Position p,Item i)  
  146. {  
  147.     p->data = i;  
  148. }  
  149.   
  150. /*删除链表中的尾节点并返回地址,改变链表的尾指针指向新的尾节点*/  
  151. PNode Remove(DList *plist)  
  152. {  
  153.     Position p=NULL;  
  154.     if(IsEmpty(plist))  
  155.         return NULL;  
  156.     else  
  157.     {  
  158.         p = GetTail(plist);  
  159.         p->previous->next = p->next;  
  160.         plist->tail = p->previous;  
  161.         plist->size--;  
  162.         return p;  
  163.     }  
  164. }  
  165. /*在链表中p位置之前插入新节点s*/  
  166. PNode InsBefore(DList *plist,Position p,PNode s)  
  167. {  
  168.     s->previous = p->previous;  
  169.     s->next = p;  
  170.     p->previous->next = s;      
  171.     p->previous = s;  
  172.   
  173.     plist->size++;  
  174.     return s;  
  175. }  
  176. /*在链表中p位置之后插入新节点s*/  
  177. PNode InsAfter(DList *plist,Position p,PNode s)  
  178. {  
  179.     s->next = p->next;  
  180.     s->previous = p;  
  181.       
  182.     if(p->next != NULL)  
  183.         p->next->previous = s;  
  184.     p->next = s;  
  185.       
  186.     if(p = GetTail(plist))  
  187.         plist->tail = s;  
  188.       
  189.     plist->size++;  
  190.     return s;  
  191. }  
  192.   
  193. /*返回在链表中第i个节点的位置*/  
  194. PNode LocatePos(DList *plist,int i)  
  195. {  
  196.     int cnt = 0;  
  197.     Position p = GetHead(plist);  
  198.     if(i>GetSize(plist)||i<1)  
  199.         return NULL;  
  200.   
  201.     while(++cnt<=i)  
  202.     {  
  203.         p=p->next;  
  204.     }  
  205.   
  206.     return p;  
  207. }  
  208.   
  209. /*依次对链表中每个元素调用函数visit()*/  
  210. void ListTraverse(DList *plist,void (*visit)())  
  211. {  
  212.     Position p = GetHead(plist);  
  213.     if(IsEmpty(plist))  
  214.         exit(0);  
  215.     else  
  216.     {  
  217.           
  218.         while(p->next!=NULL)  
  219.         {  
  220.             p = p->next;  
  221.             visit(p->data);              
  222.         }          
  223.     }  
  224. }  
test.c

[cpp] view plaincopy
  1. #include"DList.h"  
  2. #include<stdio.h>  
  3. void print(Item i)  
  4. {  
  5.     printf("数据项为%d \n",i);  
  6. }  
  7. main()  
  8. {  
  9.     DList *plist = NULL;  
  10.     PNode p = NULL;  
  11.       
  12.     plist = InitList();  
  13.     p = InsFirst(plist,MakeNode(1));  
  14.     InsBefore(plist,p,MakeNode(2));  
  15.     InsAfter(plist,p,MakeNode(3));  
  16.   
  17.     printf("p前驱位置的值为%d\n",GetItem(GetPrevious(p)));  
  18.     printf("p位置的值为%d\n",GetItem(p));  
  19.     printf("p后继位置的值为%d\n",GetItem(GetNext(p)));  
  20.       
  21.       
  22.     printf("遍历输出各节点数据项:\n");  
  23.     ListTraverse(plist,print);  
  24.     printf("除了头节点该链表共有%d个节点\n",GetSize(plist));  
  25.     FreeNode(DelFirst(plist));  
  26.     printf("删除第一个节点后重新遍历输出为:\n");  
  27.     ListTraverse(plist,print);  
  28.     printf("除了头节点该链表共有%d个节点\n",GetSize(plist));  
  29.     DestroyList(plist);  
  30.     printf("链表已被销毁\n");  
  31. }  

执行结果如下:

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

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

相关文章

执行shell出现bad interpreter

执行shell出现bad interpreter:No such file or directory linux执行shell出现bad interpreter:No such file or directory的原因是文件格式的问题。这个文件是在Windows下编写的。换行的方式与Unix不一样&#xff0c;但是在VI下面如果不Set一下又完全看不出来。 解决方法&…

exports、module.exports和export、export default到底是咋回事

前言 难得有空&#xff0c;今天开始重新规范的学习一下node编程。 但是引入模块我看到用 require的方式&#xff0c;再联想到咱们的ES6各种export 、export default。 阿西吧&#xff0c;头都大了.... 头大完了&#xff0c;那我们坐下先理理他们的使用范围。 require: node …

linux自动备份网站和数据库,到另外服务器上,为当前用户创建定时任务

2019独角兽企业重金招聘Python工程师标准>>> 两台服务器111&#xff0c;和117服务器,每天完成111服务器上网站和数据库自动备份到117服务器上 1&#xff1a;我的111服务器上是当前用户&#xff1a;sx A: 查看当前用户的计划任务&#xff1a;crontab -l是查看当前…

自定义控件三部曲之动画篇(一)——alpha、scale、translate、rotate、set的xml属性及用法...

前言&#xff1a;这几天做客户回访&#xff0c;感触很大&#xff0c;用户只要是留反馈信息&#xff0c;总是一种恨铁不成钢的心态&#xff0c;想用你的app&#xff0c;却是因为你的技术问题&#xff0c;让他们不得不放弃&#xff0c;而你一个回访电话却让他们尽释前嫌&#xff…

Linux c 算法与数据结构--栈

前段时间写了双向链表&#xff0c;现在写个栈&#xff0c;写之前&#xff0c;先简单介绍链表 队列  栈的区别&#xff1a; 链表&#xff0c;队列&#xff0c;堆栈的区别 1、栈是个有底的口袋&#xff0c;像袜子。 队列是没底的口袋&#xff0c;像通心粉。 所以&#xff1a;栈…

关于sass(scss)、less、postcss、stylus等的用法与区别

一. Sass/Scss、Less、stylus是什么? 它们都是css预处理器。css预处理器的概念&#xff1a;CSS预处理器用一种专门的编程语言&#xff0c;进行Web页面样式设计&#xff0c;然后再编译成正常的CSS文件&#xff0c;以供项目使用。CSS预处理器为CSS增加一些编程的特性&#xff0…

计算机点滴

CD&#xff0c;VCD&#xff0c;DVD的区别CD:纯音乐 VCD&#xff1a;影视初级光盘 DVD&#xff1a;高清晰影视光盘 EVD&#xff1a;高清晰数码影视 MPEG4&#xff1a;压缩高密影视光盘 MP3&#xff1a;压缩纯音乐1.容量大小不同&#xff1a;DVD可以装更多的内容。CD与DVD差别在于…

Linux C 算法与数据结构 --二叉树

头文件BiTree.h [cpp] view plaincopy typedef int Item; typedef struct node { struct node * lchild; struct node * rchild; Item data; }BiTNode,*BiTree; /*构造一棵新的二叉树*/ BiTree InitBiTree(BiTNode *root); /*生成节点*/ …

Spring 实现数据库读写分离

Spring 实现数据库读写分离 现在大型的电子商务系统&#xff0c;在数据库层面大都采用读写分离技术&#xff0c;就是一个Master数据库&#xff0c;多个Slave数据库。Master库负责数据更新和实时数据查询&#xff0c;Slave库当然负责非实时数据查询。因为在实际的应用中&#xf…

vue 3.x 中使用ele-image时相对路径的图片加载失败

参考文档&#xff1a; https://element.eleme.cn/#/zh-CN/component/installation 环境: Mac OS X 10.12 [zcmele 2]$node -v v12.6.0 [zcmele 3]$npm -v 6.9.0 [zcmele 4]$cnpm -v cnpm6.1.0 (/usr/local/lib/node_modules/cnpm/lib/parse_argv.js) npm6.10.2 (/usr/local/li…

JavaScript函数绑定

一个简单的函数绑定 在JavaScript与DOM交互中经常需要使用函数绑定&#xff0c;定义一个函数然后将其绑定到特定DOM元素或集合的某个事件触发程序上&#xff0c;绑定函数经常和回调函数及事件处理程序一起使用&#xff0c;以便把函数作为变量传递的同时保留代码执行环境。 <…

ie6兼容问题汇总

这几天在查找和解决网页在ie6下的兼容性问题花了我不少的时间&#xff0c;参考了网上的一些解决方法和自己做出来比较有效果的给大家参考一下&#xff0c;也方便我日后再用到&#xff1a; 1.IE的cache设置为Every visit to the page&#xff0c;而不是默认的Automatically。基本…

Linux C 数据结构---线性表

数据结构指的是数据元素及数据元素之间的相互关系&#xff0c;包含下面三方面的内容&#xff1a; 其中&#xff0c;线性表是最基本、最简单、也是最常用的一种数据结构。线性表中数据元素之间的关系是一对一的关系&#xff0c;即除了第一个和最后一个数据元素之外&#xff0c;其…

Postman发送请求时带上登录信息

正常情况下&#xff0c;没有登录验证等公共接口&#xff0c;用postman进行get或post请求都很方便&#xff0c;加上相应的参数就行。 但是对于某些接口&#xff0c;可能需要先登录后才能请求&#xff0c;这时如果按正常的思路请求&#xff0c;可能就会被拦截了。 对于这种情况…

Chrome跨域问题

2019独角兽企业重金招聘Python工程师标准>>> 在chrome图标&#xff0c;右键--->属性 --->目标 路径末尾添加 “--disable-web-security” 重启即可 转载于:https://my.oschina.net/u/861562/blog/152171

解决安装mysql的”A Windows service with the name MySQL already exists.“问题

如果以前安装过mysql&#xff0c;卸载重装&#xff0c;很可能会碰到”A Windows service with the name MySQL already exists.“这样的提示。即服务已经存在。我们可以在window任务管理器----服务中查看&#xff0c;发现确实存在&#xff0c;没有卸载干净。 解决这个问题&…

[vue] 父子组件间传值

环境说明: vue 3.x ant-vue 父组件(Album.vue)使用: <template><div><a-button type"primary" icon"plus" click"uploadImage">图片</a-button><upload-image :visible.sync"visible"></upload-i…

Linux C 数据结构---单向链表

线性表存储结构分为顺序存储、链式存储。 顺序存储的优点&#xff1a; 顺序存储的缺点&#xff1a; 链表就是典型的链式存储&#xff0c;将线性表L &#xff08;a0,a1,a2,........an-1&#xff09;中个元素分布在存储器的不同存储块&#xff0c;成为结点&#xff08;Node&…

杂感

成功的IT大佬&#xff0c;我读着沸腾十五年&#xff0c;激荡三十年&#xff0c;知识英雄&#xff0c;满腔热血&#xff0c;梦想真的是个好东西&#xff0c;让你在这个国度不至于行尸走肉。走上编程这条路&#xff0c;有人因走投无路而走此路&#xff0c;有人怀抱着梦想&#xf…

分页插件--根据Bootstrap Paginator改写的js插件

刚刚出来实习&#xff0c;之前实习的公司有一个分页插件&#xff0c;和后端的数据字典约定好了的&#xff0c;基本上是看不到内部是怎么实现的&#xff0c;新公司是做WPF的&#xff0c;好像对于ASP.NET的东西不多&#xff0c;导师扔了一个小系统给我和另一个同事&#xff0c;指…