当前位置:   article > 正文

C语言实现单链表_c语言单链表实现

c语言单链表实现

一、什么是链表

        链表是用来作为一种数据结构来存储数据的,它可以做到需要存储一个数据时便会向内存空间申请一块地址,并不会产生空间上的浪费。本篇博客将介绍单链表的功能以及实现。

二、代码的实现

        单链表在具体更改其存储的数据时,需要用到二级指针。因为我们在最开始定义单链表时创建的结构体指针指向NULL,而它的类型是结构体指针,我们如果想要改变实参就需要穿这个结构体指针的地址,再进行解应用来完成单链表的功能。而在打印、查询等不需要更改单链表内容的功能中,我们只用一级指针便可以完成相应的功能。

        具体实现方法在注释中,供借鉴。我们需要三个文件。

        SList.h用来存放一些函数以及其他所需变量的声明。

        SList.c用来实现函数的定义。

        list_test.c用来进行测试。

  1. //SList.h文件
  2. #pragma once
  3. #include <stdio.h>
  4. #include <stdlib.h>
  5. #include <assert.h>
  6. //一些需要的库函数
  7. typedef int SLType;//便于更改,重定义单链表存储的数据类型
  8. typedef struct SList
  9. {
  10. struct SList * next;
  11. SLType data;
  12. }SL;
  13. //定义结构体,由于单链表是一个结点找到下一个结点,
  14. //所以应当采用结构体指针来存储下一个结点的地址
  15. void SLPush(SL** pphead,SLType x);//尾插
  16. void SLPrint(SL* phead);//打印
  17. void SLPop(SL** pphead);//尾删
  18. void SLPushFront(SL** pphead, SLType x);//头插
  19. void SLPopFront(SL** pphead);//头删
  20. int SLFind(SL* phead,SLType x);//查找
  21. void SLInsert(SL** pphead, int pos, SLType x);//在指定位置插入一个元素
  22. void SLPopPos(SL** pphead, int pos);//删除指定位置元素

        

  1. SList.c文件
  2. #define _CRT_SECURE_NO_WARNINGS 1
  3. #include "SList.h"
  4. void SLPush(SL** pphead, SLType x)//尾插功能的实现,传入的是头指针的地址
  5. {
  6. SL* newNode = (SL*)malloc(4 + sizeof(SLType));
  7. newNode->next = NULL;
  8. newNode->data = x;//创建最后一个尾结点
  9. if (*pphead == NULL)//单链表为空的情况下
  10. {
  11. *pphead = newNode;
  12. }//则直接解应用把我们的头指针指向创建的结点
  13. else//如果链表不为空的情况下
  14. {
  15. SL* ptail = *pphead;//创建一个尾指针来寻找最后一个结点
  16. while (ptail->next != NULL)
  17. {
  18. ptail = ptail->next;
  19. }//找到最后一个结点
  20. ptail->next = newNode;//把最后一个结点的next指向新创建的结点
  21. }
  22. }
  23. void SLPrint(SL* phead)//单链表的打印
  24. {
  25. if (phead == NULL)//链表为空的情况下
  26. {
  27. printf("NULL");//直接打印NULL
  28. }
  29. else
  30. {
  31. while (phead->next != NULL)
  32. {
  33. printf("%d", phead->data);
  34. printf("->");
  35. phead = phead->next;
  36. }//打印到最后一个结点的前一个结点
  37. printf("%d", phead->data);//打印最后一个结点
  38. printf("\n");
  39. }
  40. }
  41. void SLPop(SL** pphead)//尾删操作
  42. {
  43. if (*pphead == NULL)//在链表为空的情况下,直接采用暴力方式退出
  44. {
  45. assert(*pphead);
  46. exit(-1);
  47. }
  48. else if ((*pphead)->next == NULL)//链表只有一个元素的情况下
  49. {
  50. free(*pphead);//释放掉唯一一个结点的空间
  51. *pphead = NULL;//把头指针重新指向NULL
  52. }
  53. else//链表由两个及两个元素的情况下
  54. {
  55. SL* ptail = *pphead;//定义ptail指针来找到尾结点
  56. SL* prev = ptail;//定义一个prev指针来找到最后一个结点的前一个结点
  57. while (ptail->next != NULL)
  58. {
  59. prev = ptail;
  60. ptail = ptail->next;
  61. }//完成上述操作
  62. free(ptail);//释放掉最后一个结点的空间
  63. prev->next = NULL;//将尾结点的上一个结点的next指向NULL
  64. }
  65. }
  66. void SLPushFront(SL** pphead, SLType x)//头插
  67. {
  68. SL* newNode = (SL*)malloc(4 + sizeof(SLType));
  69. newNode->next = NULL;
  70. newNode->data = x;//创建新结点
  71. if (*pphead == NULL)//链表中没有元素
  72. {
  73. *pphead = newNode;//把头指针直接指向新节点
  74. }
  75. else//链表中有至少一个元素
  76. {
  77. SL* temP = *pphead;//将最初头指针指向的结点的地址存放在一个临时变量中
  78. newNode->next = temP;//新节点的next指向原来的第一个结点
  79. *pphead = newNode;//把头指针指向新节点
  80. }
  81. }
  82. void SLPopFront(SL** pphead)//头删
  83. {
  84. if (*pphead == NULL)//如果链表中没有元素直接警告
  85. {
  86. assert(*pphead!=NULL);
  87. exit(-1);
  88. }
  89. else//链表中有至少一个元素
  90. {
  91. SL* temP = (*pphead)->next;
  92. free(*pphead);
  93. *pphead = temP;
  94. }
  95. }
  96. int SLFind(SL* phead,SLType x)//查找,如果查找到元素则返回位置,没找到则返回0
  97. {
  98. int count = 1;//记录元素在第几个结点
  99. assert(phead != NULL);//判断链表是否为空
  100. while (phead->next != NULL)
  101. {
  102. if (phead->data == x)
  103. {
  104. return count;
  105. }
  106. count++;
  107. phead = phead->next;
  108. }//判断到尾结点的前一个结点
  109. if (phead->data == x)//判断尾结点
  110. return count;
  111. printf("没找到\n");
  112. return 0;
  113. }
  114. void SLInsert(SL** pphead, int pos, SLType x)//在指定位置插入元素
  115. {
  116. SL* des = *pphead;//用来找到目标位置的后一个位置
  117. SL* prev = *pphead;//用来找到目标位置
  118. SL* newNode = (SL*)malloc(4 + sizeof(SLType));
  119. newNode->data = x;
  120. newNode->next = (*pphead);//创建新结点
  121. if (pos == 1)
  122. {
  123. *pphead = newNode;//如果pos为1,则按头插处理
  124. }
  125. else//其他情况下,由于暴力退出,不可以在最后插入元素
  126. {
  127. for (int i = 1; i < pos; i++)//循环找到需要插入元素的位置
  128. {
  129. prev = des;
  130. des = des->next;
  131. assert(des!=NULL);//判断pos是否合法
  132. }
  133. newNode->next = des;//把新节点的next指向pos的下一个结点的地址
  134. prev->next = newNode;//前一个结点的next指向新的结点
  135. }
  136. }
  137. void SLPopPos(SL** pphead, int pos)//删除指定位置元素
  138. {
  139. assert(*pphead != NULL);//判断链表是否为空
  140. SL* pdes = *pphead;//找到指定位置
  141. SL* prev = NULL;//找到指定位置的前一个位置
  142. for (int i = 1; i < pos; i++)
  143. {
  144. prev = pdes;
  145. pdes = pdes->next;
  146. assert(pdes != NULL);//判断pos是否
  147. }//完成上述操作
  148. if (pos == 1)//如果pos为1按头删处理
  149. {
  150. SL* tem = (*pphead)->next;
  151. free(*pphead);
  152. *pphead = tem;
  153. }
  154. else//其他情况下
  155. {
  156. SL* tem = pdes->next;
  157. free(pdes);//释放被删除的空间
  158. prev->next = tem;
  159. }
  160. }
  1. list_test.c文件下
  2. #define _CRT_SECURE_NO_WARNINGS 1
  3. #include "SList.h"
  4. int main()
  5. {
  6. return 0;
  7. }

读者可自己进行测试,在x86的环境下。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/weixin_40725706/article/detail/646002
推荐阅读
相关标签
  

闽ICP备14008679号