找回密码
 立即注册
首页 业界区 科技 单向链表的初始化、插入、删除、遍历

单向链表的初始化、插入、删除、遍历

左丘雅秀 2025-6-27 15:12:12
  1. /********************************************************************
  2. *   file name: LnList.c
  3. *   author   :  MINDSETT@163.com
  4. *   date     :  2025/6/24
  5. *   function :  实现一个单向不循环链表的接口,可实现链表的增删改查,另外为了提高可移植性,所以链表中
  6. *               数据元素的类型为DataType_t,用户可以根据实际情况修改链表中元素的类型
  7. *   note     :  None
  8. *
  9. *   CopyRight (c)  2025  MINDSETT@163.com  All Right Reserved
  10. ********************************************************************/
  11. #include <stdio.h>
  12. #include <stdlib.h>
  13. #include <stdbool.h>
  14. //指定链表中元素的数据类型,用户可根据需要进行修改
  15. typedef int DataType_t;
  16. //构造链表的结点,链表中所有结点的数据类型应该是相同的(数据域+指针域)
  17. typedef struct SingleLinkedList
  18. {
  19.     DataType_t                  data;   //结点的数据域
  20.     struct SingleLinkedList *   next;   //结点的指针域
  21. }LnList_t;
  22. /********************************************************************
  23. *   name     :  Seqlist_Creat
  24. *   function :  创建一个空链表,空链表应该有一个头节点,对链表进行初始化
  25. *   argument :  None
  26. *   retval   :  返回头结点的地址
  27. *   author   :  MINDSETT@163.com
  28. *   date     :  2025/6/24
  29. *   note     :  None
  30. *
  31. * ******************************************************************/
  32. LnList_t *LnList_Create(void)
  33. {
  34.     //创建一个头结点并对头结点申请内存
  35.     LnList_t* Head=(LnList_t*)calloc(1,sizeof(LnList_t));
  36.     if (NULL==Head){
  37.         perror("calloc memory for Head is failed\n");
  38.         exit(-1);
  39.     }
  40.     //对头结点进行初始化
  41.     Head->next=NULL;
  42.     //将头结点的地址返回
  43.     return Head;
  44. }
  45. /********************************************************************
  46. *   name     :  LnList_NewNode
  47. *   function :  创建一个新结点,并为新结点申请堆内存以及对新结点的数据域和指针域进行初始化
  48. *   argument :  
  49. *               @data:新结点的数据
  50. *   retval   :  返回新结点的地址
  51. *   author   :  MINDSETT@163.com
  52. *   date     :  2025/6/24
  53. *   note     :  None
  54. *
  55. * ******************************************************************/
  56. LnList_t * LnList_NewNode(DataType_t data)
  57. {
  58.     //创建新结点,并未新结点申请堆内存
  59.     LnList_t * New=(LnList_t*)calloc(1,sizeof(LnList_t));
  60.      if (NULL==New){
  61.         perror("calloc memory for NewNode is failed\n");
  62.         return NULL;
  63.     }
  64.     //对新结点的数据域和指针域进行初始化
  65.     New->data=data;
  66.     New->next=NULL;
  67.     return New;
  68. }
  69. /********************************************************************
  70. *   name     :  LnList_FirstInsert
  71. *   function :  创建一个新结点,并把新结点插入链表的首部
  72. *   argument :  
  73. *               @Head:插入的链表
  74. *               @data:新结点的数据
  75. *   retval   :  成功返回true,失败返回false
  76. *   author   :  MINDSETT@163.com
  77. *   date     :  2025/6/24
  78. *   note     :  None
  79. *
  80. * ******************************************************************/
  81. bool LnList_FirstInsert(LnList_t * Head,DataType_t data)
  82. {
  83.     //创建新结点,并对新结点进行初始化
  84.     LnList_t* New=LnList_NewNode(data);
  85.     if (NULL==New){
  86.         perror("Create New node is failed\n");
  87.         return false;
  88.     }
  89.     //判断链表是否为空,如果为空,则将新结点直接插入
  90.     if (NULL==Head->next){
  91.         Head->next=New;
  92.         return true;
  93.     }
  94.     //如果链表为非空,则将新结点插入链表的首部
  95.     New->next=Head->next;
  96.     Head->next=New;
  97.     return true;
  98. }
  99. /********************************************************************
  100. *   name     :  LnList_TailInsert
  101. *   function :  创建一个新结点,并把新结点插入链表的尾部
  102. *   argument :  
  103. *               @Head:插入的链表
  104. *               @data:新结点的数据
  105. *   retval   :  成功返回true,失败返回false
  106. *   author   :  MINDSETT@163.com
  107. *   date     :  2025/6/24
  108. *   note     :  None
  109. *
  110. * ******************************************************************/
  111. bool LnList_TailInsert(LnList_t * Head,DataType_t data)
  112. {
  113.     //创建新结点,并对新结点进行初始化
  114.     LnList_t* New=LnList_NewNode(data);
  115.     if (NULL==New){
  116.         perror("Create New node is failed\n");
  117.         return false;
  118.     }
  119.     //判断链表是否为空,如果为空,则将新结点直接插入
  120.     if (NULL==Head->next){
  121.         Head->next=New;
  122.         return true;
  123.     }
  124.     //如果链表为非空,则链表的头结点的地址进行备份,循环找到链表的尾部,并将新结点插入链表的尾部
  125.     LnList_t *Phead=Head;
  126.     while(Phead->next){
  127.         Phead=Phead->next;
  128.     }
  129.     Phead->next=New;
  130.     return true;
  131. }
  132. /********************************************************************
  133. *   name     :  LnList_DestInsert
  134. *   function :  创建一个新结点,并把新结点插入链表的指定位置
  135. *   argument :  
  136. *               @Head:插入的链表
  137. *               @Dest:指定需要新结点插入位置的直接前驱的数据
  138. *               @data:新结点的数据
  139. *   retval   :  成功返回true,失败返回false
  140. *   author   :  MINDSETT@163.com
  141. *   date     :  2025/6/24
  142. *   note     :  None
  143. *
  144. * ******************************************************************/
  145. bool LnList_DestInsert(LnList_t * Head,DataType_t Dest,DataType_t data)
  146. {
  147.     //创建新结点,并对新结点进行初始化
  148.     LnList_t* New=LnList_NewNode(data);
  149.     if (NULL==New){
  150.         perror("Create New node is failed\n");
  151.         return false;
  152.     }
  153.     //判断链表是否为空,如果为空,则将新结点直接插入
  154.     if (NULL==Head->next){
  155.         Head->next=New;
  156.         return true;
  157.     }
  158.     //如果链表为非空,遍历链表,目的是找到目标结点,比较结点的数据域
  159.     LnList_t *Phead=Head->next;
  160.     while(Phead!=NULL && Dest!=Phead->data){
  161.         Phead=Phead->next;
  162.     }
  163.     if(NULL==Phead){
  164.         printf("Dest is not found\n");
  165.         return false;
  166.     }
  167.     //找到目标结点,则把新结点加入到目标结点的后面
  168.     New->next=Phead->next;
  169.     Phead->next=New;
  170.     return true;
  171. }
  172. /********************************************************************
  173. *   name     :  LnList_FirstDel
  174. *   function :  删除链表的首结点
  175. *   argument :  
  176. *               @Head:链表的头结点
  177. *   retval   :  成功返回true,失败返回false
  178. *   author   :  MINDSETT@163.com
  179. *   date     :  2025/6/24
  180. *   note     :  None
  181. *
  182. * ******************************************************************/
  183. bool LnList_FirstDel(LnList_t* Head)
  184. {
  185.     //判断链表是否为空
  186.     if (NULL==Head || NULL==Head->next){
  187.         perror("Linked list is empty\n");
  188.         return false;
  189.     }
  190.     //备份链表的头结点和首结点
  191.     LnList_t* Pfirst=Head->next;
  192.     //将头结点的指针域指向首结点的指针域
  193.     Head->next=Pfirst->next;
  194.     //释放首结点占用的内存
  195.     Pfirst->next=NULL;
  196.     free(Pfirst);
  197.     return true;
  198. }
  199. /********************************************************************
  200. *   name     :  LnList_TailDel
  201. *   function :  删除链表的尾结点
  202. *   argument :  
  203. *               @Head:链表的头结点
  204. *   retval   :  成功返回true,失败返回false
  205. *   author   :  MINDSETT@163.com
  206. *   date     :  2025/6/24
  207. *   note     :  None
  208. *
  209. * ******************************************************************/
  210. bool LnList_TailDel(LnList_t* Head)
  211. {
  212.     //判断链表是否为空
  213.     if (NULL==Head || NULL==Head->next){
  214.         perror("Linked list is empty\n");
  215.         return false;
  216.     }
  217.     //备份链表的头结点和首结点
  218.     LnList_t* Phead=Head;
  219.     LnList_t* Pfirst=Phead->next;
  220.     //循环找到链表的尾结点和尾结点的直接前驱
  221.     while(Pfirst->next){
  222.         Pfirst=Pfirst->next;
  223.         Phead=Phead->next;
  224.     }
  225.     //将尾结点的直接前驱的指针域指向为NULL
  226.     Phead->next=NULL;
  227.     //释放尾结点占用的内存
  228.     free(Pfirst);
  229.     return true;
  230. }
  231. /********************************************************************
  232. *   name     :  LnList_DestDel
  233. *   function :  删除链表的指定结点
  234. *   argument :  
  235. *               @Head:链表的头结点
  236. *               @Dest:需要删除的指定结点
  237. *   retval   :  成功返回true,失败返回false
  238. *   author   :  MINDSETT@163.com
  239. *   date     :  2025/6/24
  240. *   note     :  None
  241. *
  242. * ******************************************************************/
  243. bool LnList_DestDel(LnList_t* Head,DataType_t Dest)
  244. {
  245.     //判断链表是否为空
  246.     if (NULL==Head || NULL==Head->next){
  247.         perror("Linked list is empty\n");
  248.         return false;
  249.     }
  250.     //Phead指向前驱,Pfirst指向当前结点
  251.     LnList_t* Phead=Head;
  252.     LnList_t* Pfirst=Phead->next;
  253.     //遍历链表,目的是找到目标结点,比较结点的数据域
  254.     while(Pfirst!=NULL && Dest!=Pfirst->data){
  255.         Phead=Pfirst;
  256.         Pfirst=Pfirst->next;
  257.     }
  258.     if(NULL==Pfirst){
  259.         printf("Dest is not found\n");
  260.         return false;
  261.     }
  262.     //删除目标结点——将指定结点的直接前驱的指针域指向指定结点的直接后继
  263.     Phead->next=Pfirst->next;
  264.     //释放指定结点占用的内存
  265.     Pfirst->next=NULL;
  266.     free(Pfirst);
  267.     return true;
  268. }
  269. /********************************************************************
  270. *   name     :  LnList_Print
  271. *   function :  遍历输出链表中各个结点的数据
  272. *   argument :  
  273. *               @Head:需要遍历的链表
  274. *   retval   :  None
  275. *   author   :  MINDSETT@163.com
  276. *   date     :  2025/6/24
  277. *   note     :  None
  278. *
  279. * ******************************************************************/
  280. void LnList_Print(LnList_t* Head)
  281. {
  282.     //判断链表是否为空
  283.     if (NULL==Head || NULL==Head->next){
  284.         perror("Linked list is empty\n");
  285.         return ;
  286.     }
  287.     //对链表的头节点的地址进行备份
  288.     LnList_t *Phead=Head;
  289.     //循环遍历链表
  290.     while(Phead->next){
  291.         //把头结点的直接后继作为新的头结点
  292.         Phead= Phead->next;
  293.         //输出头结点的直接后继的数据域
  294.         printf("Data=%d\n",Phead->data);
  295.     }
  296. }
复制代码
来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
您需要登录后才可以回帖 登录 | 立即注册