当前位置:   article > 正文

C语言单向不循环链表_链表输入如何停止

链表输入如何停止

目录

链表的概念

 1、设计节点类型

2、创建链表 

3、头插法 

 4、尾插法

​ 5、打印链表节点数据

6、头删法 

 7、尾删法

 8、链表节点数据个数

9、指定位置插入

10、指定位置删除

11、链表冒泡排序

12、菜单 

整体代码显示

测试

链表的概念

链表的两种结构

物理结构和逻辑结构

物理 存储单元 上非连续、非顺序的 存储结构,

逻辑上是连续的,他们之间用指针连续起来

链表中每一个元素称为节点,由一系列的节点组成。

每个节点包括两部分,存储数据元素的数据域(data)和存储下一个节点地址的指针域(next)。

如图所示:下图有四个节点,头节点一般不存数据,head为头节点,next为指向下一个节点的

指针(存储下一个节点的地址),单向不循环链表最后一个节点的指针域,指向空(NULL)。

 1、设计节点类型

  1. /**************设计节点类型**************/
  2. typedef struct ListNode
  3. {
  4. int data; //数据域
  5. struct ListNode *next; //地址域
  6. } node_t;

2、创建链表 

申请头节点空间

  1. /********创建链表********/
  2. node_t *CreateList()
  3. {
  4. node_t *head = (node_t *)malloc(sizeof(node_t)); //申请头节点空间
  5. if (head == NULL)
  6. {
  7. perror("head is null\n"); //如果空间申请失败报错
  8. return NULL;
  9. }
  10. head->data = 0; //头节点数据域不放数据,初始化
  11. head->next = NULL;
  12. return head;
  13. }

3、头插法 

  1. /************头插法************/
  2. int InsertHListNode(node_t *head, int newdata)
  3. {
  4. // 1、判断
  5. if (head == NULL)
  6. {
  7. perror("head is null\n");
  8. return -1;
  9. }
  10. // 2、申请新节点空间
  11. node_t *newnode = (node_t *)malloc(sizeof(node_t));
  12. if (newnode == NULL)
  13. {
  14. perror("newnode is null\n");
  15. return -1;
  16. }
  17. // 3、填写数据
  18. newnode->data = newdata;
  19. // 4、修改指针
  20. newnode->next = head->next;
  21. head->next = newnode; //头节点指向新节点
  22. return 0;
  23. }

头插法就是在头节点后插入新节点(头节点不放数据所以从头节点后一个位置插入),核心就是 将新节点两条线连接起来

 

 4、尾插法

  1. /************尾插法************/
  2. int InserttListNode(node_t *head, int newdata)
  3. {
  4. // 1、判断
  5. if (head == NULL)
  6. {
  7. perror("head is null\n");
  8. return -1;
  9. }
  10. // 2、申请新节点空间
  11. node_t *newnode = (node_t *)malloc(sizeof(node_t));
  12. if (newnode == NULL)
  13. {
  14. perror("malloc error\n");
  15. return -1;
  16. }
  17. // 3、填写数据
  18. newnode->data = newdata;
  19. // 4、找尾
  20. node_t *temp = head; //因为头节点不能动所以申请一个中间变量
  21. while (temp->next != NULL) //当temp->next = NULL时跳出循环
  22. {
  23. temp = temp->next;
  24. }
  25. // 5、修改指针
  26. newnode->next = temp->next; //新节点指向最后
  27. temp->next = newnode; //新节点接到最后一个节点后
  28. return 0;
  29. }

尾插法 核心就是找尾,找到尾后修改指针的指向,代码中的指针指向跟图中的指针指向是同一个意思,只是写法不同。

 5、打印链表节点数据

遍历, 循环打印,将链表中的所有的节点数据打印到终端

  1. /*************打印链表***************/
  2. void PrintList(node_t *head)
  3. {
  4. if (head == NULL)
  5. {
  6. perror("There is no data in the linked list, please input it first\n");
  7. return;
  8. }
  9. node_t *temp = head;
  10. while (temp->next != NULL)
  11. {
  12. temp = temp->next; //因为头节点不放数据所以从第二个节点开始
  13. printf("%d\t", temp->data);
  14. }
  15. printf("\n");
  16. }

6、头删法 

  1. /***************头删法*******************/
  2. int DeleteHList(node_t *head)
  3. {
  4. if (head == NULL)
  5. {
  6. perror("head is null\n");
  7. return -1;
  8. }
  9. //设置一个临时变量
  10. node_t *temp = head->next;
  11. head->next = temp->next;
  12. free(temp); //删除成功释放空间
  13. temp = NULL;
  14. return 0;
  15. }

头删法:相对来说是比较简单的,只需要改变一个指针指向。

 7、尾删法

  1. /***************尾删法*******************/
  2. int DeleteTList(node_t *head)
  3. {
  4. if (head == NULL)
  5. {
  6. perror("head is null\n");
  7. return -1;
  8. }
  9. //设置一个临时变量
  10. node_t *prev = NULL; //指向尾的前一个节点
  11. node_t *temp = head;
  12. //找尾
  13. while (temp->next->next != NULL)
  14. {
  15. temp = temp->next;
  16. }
  17. prev = temp;
  18. temp = temp->next;
  19. prev->next = NULL;
  20. free(temp);
  21. temp = NULL;
  22. return 0;
  23. }

尾删法:找两个节点先找倒是第二个,在通过倒数第二个找到最后一个,找最后一个是为了释放节点空间。

 8、链表节点数据个数

遍历整个链表,然后返回节点数据个数(因为头节点不放数据所以不包括头节点)

  1. /****************链表的节点元素个数**********************/
  2. int ListLength(node_t *head)
  3. {
  4. if (head == NULL)
  5. {
  6. perror("head is null\n");
  7. return -1;
  8. }
  9. node_t *temp = head;
  10. int i = 0;
  11. while (temp->next != NULL)
  12. {
  13. temp = temp->next;
  14. i++;
  15. }
  16. return i;
  17. }

9、指定位置插入

  1. /***************指定位置插入***************/
  2. int InsertLocaList(node_t *head, int newdata, int loca)
  3. {
  4. //判错
  5. int len = ListLength(head);
  6. if (head == NULL || loca <= 0 || loca > len + 1) //插入的位置超范围
  7. {
  8. perror("head is null or out of scope\n");
  9. return -1;
  10. }
  11. //申请新节点空间
  12. node_t *newnode = (node_t *)malloc(sizeof(node_t));
  13. if (newnode == NULL)
  14. {
  15. perror("malloc error\n");
  16. return -1;
  17. }
  18. //填写数据,建立联系
  19. newnode->data = newdata;
  20. node_t *temp = head;
  21. int i = 1;
  22. while (loca != i)
  23. {
  24. temp = temp->next;
  25. i++;
  26. }
  27. newnode->next = temp->next;
  28. temp->next = newnode;
  29. return 0;
  30. }

在写之前一定要判断该链表和该位置是否为空,如果都不存在链表和该位置,要插入的节点就接不上了。 

10、指定位置删除

  1. /***************指定位置删除***************/
  2. int DeleteLocaList(node_t *head, int loca)
  3. {
  4. //判错
  5. int len = ListLength(head);
  6. if (head == NULL || loca <= 0 || loca > len) //删除的位置超范围
  7. {
  8. perror("head is null or out of scope\n");
  9. return -1;
  10. }
  11. node_t *prev = NULL; //指向尾的前一个节点
  12. node_t *temp = head;
  13. int i = 1;
  14. //找要删除节点的前一个位置
  15. while (loca != i)
  16. {
  17. temp = temp->next;
  18. i++;
  19. }
  20. prev = temp;
  21. temp = temp->next;
  22. prev->next = temp->next;
  23. return 0;
  24. }

11、链表冒泡排序

  1. /************链表冒泡排序*************/
  2. node_t *SortList(node_t *head)
  3. {
  4. if (head == NULL)
  5. {
  6. perror("head is null\n");
  7. return NULL;
  8. }
  9. int len = ListLength(head);
  10. if (len < 2)
  11. {
  12. return head;
  13. }
  14. node_t *r, *p, *q; //表示前中后三个节点位置
  15. r = head;
  16. for (int i = 0; i < len - 1; i++)
  17. {
  18. r = head;
  19. for (int j = 0; j < len - i - 1; j++)
  20. {
  21. p = r->next;
  22. q = p->next;
  23. if (q->data < p->data)
  24. {
  25. p->next = q->next;
  26. q->next = p;
  27. r->next = q;
  28. }
  29. r = r->next;
  30. }
  31. }
  32. return head;
  33. }

12、菜单 

  1. void menu(node_t *head)
  2. {
  3. char ch;
  4. while (1)
  5. {
  6. printf("***************************************\n");
  7. printf("***** 1.头插 *****\n");
  8. printf("***** 2.尾插 *****\n");
  9. printf("***** 3.头删 *****\n");
  10. printf("***** 4.尾删 *****\n");
  11. printf("***** 5.在指定位置插入 *****\n");
  12. printf("***** 6.在指定位置删除 *****\n");
  13. printf("***** 7.打印单链表 *****\n");
  14. printf("***** 8.查看链表中有多少元素 *****\n");
  15. printf("***** 9.排序 *****\n");
  16. printf("***** 0.退出 *****\n");
  17. printf("***************************************\n");
  18. int option = 0, loca = 0, newdata = 0;
  19. printf("请输入选项:> ");
  20. scanf("%d", &option);
  21. switch (option)
  22. {
  23. case 9:
  24. head = SortList(head);
  25. break;
  26. case 8:
  27. printf("链表中有%d个元素\n", ListLength(head));
  28. break;
  29. case 7:
  30. PrintList(head);
  31. break;
  32. case 6:
  33. printf("请输入你要删除的位置:");
  34. scanf("%d", &loca);
  35. DeleteLocaList(head, loca);
  36. break;
  37. case 5:
  38. printf("请输入你要插入的位置:");
  39. scanf("%d", &loca);
  40. printf("请输入你要插入的元素:");
  41. scanf("%d", &newdata);
  42. InsertLocaList(head, newdata, loca);
  43. break;
  44. case 4:
  45. DeleteTList(head);
  46. break;
  47. case 3:
  48. DeleteHList(head);
  49. break;
  50. case 2:
  51. printf("请输入你要插入的元素:");
  52. scanf("%d", &newdata);
  53. InserttListNode(head, newdata);
  54. break;
  55. case 1:
  56. printf("请输入你要插入的元素:");
  57. scanf("%d", &newdata);
  58. InsertHListNode(head, newdata);
  59. break;
  60. case 0:
  61. return;
  62. default:
  63. printf("输入错误\n");
  64. break;
  65. }
  66. printf("是否继续(y/n)\n");
  67. getchar(); //空吞
  68. ch = getchar();
  69. if (ch == 'n' || ch == 'N')
  70. {
  71. return;
  72. }
  73. }
  74. }

整体代码显示

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. /**************设计节点类型**************/
  4. typedef struct ListNode
  5. {
  6. int data; //数据域
  7. struct ListNode *next; //地址域
  8. } node_t;
  9. node_t *CreateList(); //创建链表
  10. int InsertHListNode(node_t *head, int newdata); //头插法
  11. int InserttListNode(node_t *head, int newdata); //尾插法
  12. int InsertLocaList(node_t *head, int newdata, int loca); //在指定位置插入
  13. int DeleteHList(node_t *head); //头删法
  14. int DeleteTList(node_t *head); //尾删法
  15. int DeleteLocaList(node_t *head, int loca); //在指定位置删除
  16. int ListLength(node_t *head); //链表的节点元素个数
  17. void PrintList(node_t *head); //打印链表
  18. void menu(node_t *head); //菜单
  19. node_t *SortList(node_t *head); //冒泡排序
  20. int main()
  21. {
  22. node_t *head = CreateList();
  23. if (head == NULL)
  24. {
  25. perror("head is null\n");
  26. return -1;
  27. }
  28. menu(head);
  29. return 0;
  30. }
  31. /*****************菜单***********/
  32. void menu(node_t *head)
  33. {
  34. char ch;
  35. while (1)
  36. {
  37. printf("***************************************\n");
  38. printf("***** 1.头插 *****\n");
  39. printf("***** 2.尾插 *****\n");
  40. printf("***** 3.头删 *****\n");
  41. printf("***** 4.尾删 *****\n");
  42. printf("***** 5.在指定位置插入 *****\n");
  43. printf("***** 6.在指定位置删除 *****\n");
  44. printf("***** 7.打印单链表 *****\n");
  45. printf("***** 8.查看链表中有多少元素 *****\n");
  46. printf("***** 9.排序 *****\n");
  47. printf("***** 0.退出 *****\n");
  48. printf("***************************************\n");
  49. int option = 0, loca = 0, newdata = 0;
  50. printf("请输入选项:> ");
  51. scanf("%d", &option);
  52. switch (option)
  53. {
  54. case 9:
  55. head = SortList(head);
  56. break;
  57. case 8:
  58. printf("链表中有%d个元素\n", ListLength(head));
  59. break;
  60. case 7:
  61. PrintList(head);
  62. break;
  63. case 6:
  64. printf("请输入你要删除的位置:");
  65. scanf("%d", &loca);
  66. DeleteLocaList(head, loca);
  67. break;
  68. case 5:
  69. printf("请输入你要插入的位置:");
  70. scanf("%d", &loca);
  71. printf("请输入你要插入的元素:");
  72. scanf("%d", &newdata);
  73. InsertLocaList(head, newdata, loca);
  74. break;
  75. case 4:
  76. DeleteTList(head);
  77. break;
  78. case 3:
  79. DeleteHList(head);
  80. break;
  81. case 2:
  82. printf("请输入你要插入的元素:");
  83. scanf("%d", &newdata);
  84. InserttListNode(head, newdata);
  85. break;
  86. case 1:
  87. printf("请输入你要插入的元素:");
  88. scanf("%d", &newdata);
  89. InsertHListNode(head, newdata);
  90. break;
  91. case 0:
  92. return;
  93. default:
  94. printf("输入错误\n");
  95. break;
  96. }
  97. printf("是否继续(y/n)\n");
  98. getchar(); //空吞
  99. ch = getchar();
  100. if (ch == 'n' || ch == 'N')
  101. {
  102. return;
  103. }
  104. }
  105. }
  106. /********创建链表********/
  107. node_t *CreateList()
  108. {
  109. node_t *head = (node_t *)malloc(sizeof(node_t)); //申请头节点空间
  110. if (head == NULL)
  111. {
  112. perror("head is null\n"); //如果空间申请失败报错
  113. return NULL;
  114. }
  115. head->data = 0; //头节点数据域不放数据,初始化
  116. head->next = NULL;
  117. return head;
  118. }
  119. /************头插法************/
  120. int InsertHListNode(node_t *head, int newdata)
  121. {
  122. // 1、判断
  123. if (head == NULL)
  124. {
  125. perror("head is null\n");
  126. return -1;
  127. }
  128. // 2、申请新节点空间
  129. node_t *newnode = (node_t *)malloc(sizeof(node_t));
  130. if (newnode == NULL)
  131. {
  132. perror("newnode is null\n");
  133. return -1;
  134. }
  135. // 3、填写数据
  136. newnode->data = newdata;
  137. // 4、修改指针
  138. newnode->next = head->next;
  139. head->next = newnode; //头节点指向新节点
  140. return 0;
  141. }
  142. /************尾插法************/
  143. int InserttListNode(node_t *head, int newdata)
  144. {
  145. // 1、判断
  146. if (head == NULL)
  147. {
  148. perror("head is null\n");
  149. return -1;
  150. }
  151. // 2、申请新节点空间
  152. node_t *newnode = (node_t *)malloc(sizeof(node_t));
  153. if (newnode == NULL)
  154. {
  155. perror("malloc error\n");
  156. return -1;
  157. }
  158. // 3、填写数据
  159. newnode->data = newdata;
  160. // 4、找尾
  161. node_t *temp = head; //因为头节点不能动所以申请一个中间变量
  162. while (temp->next != NULL) //当temp->next = NULL时跳出循环
  163. {
  164. temp = temp->next;
  165. }
  166. // 5、修改指针
  167. newnode->next = temp->next; //新节点指向最后
  168. temp->next = newnode; //新节点接到最后一个节点后
  169. return 0;
  170. }
  171. /*************打印链表***************/
  172. void PrintList(node_t *head)
  173. {
  174. if (head == NULL)
  175. {
  176. perror("There is no data in the linked list, please input it first\n");
  177. return;
  178. }
  179. node_t *temp = head;
  180. while (temp->next != NULL)
  181. {
  182. temp = temp->next; //因为头节点不放数据所以从第二个节点开始
  183. printf("%d\t", temp->data);
  184. }
  185. printf("\n");
  186. }
  187. /***************头删法*******************/
  188. int DeleteHList(node_t *head)
  189. {
  190. if (head == NULL)
  191. {
  192. perror("head is null\n");
  193. return -1;
  194. }
  195. //设置一个临时变量
  196. node_t *temp = head->next;
  197. head->next = temp->next;
  198. free(temp); //删除成功释放空间
  199. temp = NULL;
  200. return 0;
  201. }
  202. /***************尾删法*******************/
  203. int DeleteTList(node_t *head)
  204. {
  205. if (head == NULL)
  206. {
  207. perror("head is null\n");
  208. return -1;
  209. }
  210. //设置一个临时变量
  211. node_t *prev = NULL; //指向尾的前一个节点
  212. node_t *temp = head;
  213. //找尾
  214. while (temp->next->next != NULL)
  215. {
  216. temp = temp->next;
  217. }
  218. prev = temp;
  219. temp = temp->next;
  220. prev->next = NULL;
  221. free(temp);
  222. temp = NULL;
  223. return 0;
  224. }
  225. /****************链表的节点元素个数**********************/
  226. int ListLength(node_t *head)
  227. {
  228. if (head == NULL)
  229. {
  230. perror("head is null\n");
  231. return -1;
  232. }
  233. node_t *temp = head;
  234. int i = 0;
  235. while (temp->next != NULL)
  236. {
  237. temp = temp->next;
  238. i++;
  239. }
  240. return i;
  241. }
  242. /***************指定位置插入***************/
  243. int InsertLocaList(node_t *head, int newdata, int loca)
  244. {
  245. //判错
  246. int len = ListLength(head);
  247. if (head == NULL || loca <= 0 || loca > len + 1) //插入的位置超范围
  248. {
  249. perror("head is null or out of scope\n");
  250. return -1;
  251. }
  252. //申请新节点空间
  253. node_t *newnode = (node_t *)malloc(sizeof(node_t));
  254. if (newnode == NULL)
  255. {
  256. perror("malloc error\n");
  257. return -1;
  258. }
  259. //填写数据,建立联系
  260. newnode->data = newdata;
  261. node_t *temp = head;
  262. int i = 1;
  263. while (loca != i)
  264. {
  265. temp = temp->next;
  266. i++;
  267. }
  268. newnode->next = temp->next;
  269. temp->next = newnode;
  270. return 0;
  271. }
  272. /***************指定位置删除***************/
  273. int DeleteLocaList(node_t *head, int loca)
  274. {
  275. //判错
  276. int len = ListLength(head);
  277. if (head == NULL || loca <= 0 || loca > len) //删除的位置超范围
  278. {
  279. perror("head is null or out of scope\n");
  280. return -1;
  281. }
  282. node_t *prev = NULL; //指向尾的前一个节点
  283. node_t *temp = head;
  284. int i = 1;
  285. //找要删除节点的前一个位置
  286. while (loca != i)
  287. {
  288. temp = temp->next;
  289. i++;
  290. }
  291. prev = temp;
  292. temp = temp->next;
  293. prev->next = temp->next;
  294. return 0;
  295. }
  296. /************链表冒泡排序*************/
  297. node_t *SortList(node_t *head)
  298. {
  299. if (head == NULL)
  300. {
  301. perror("head is null\n");
  302. return NULL;
  303. }
  304. int len = ListLength(head);
  305. if (len < 2)
  306. {
  307. return head;
  308. }
  309. node_t *r, *p, *q; //表示前中后三个节点位置
  310. r = head;
  311. for (int i = 0; i < len - 1; i++)
  312. {
  313. r = head;
  314. for (int j = 0; j < len - i - 1; j++)
  315. {
  316. p = r->next;
  317. q = p->next;
  318. if (q->data < p->data)
  319. {
  320. p->next = q->next;
  321. q->next = p;
  322. r->next = q;
  323. }
  324. r = r->next;
  325. }
  326. }
  327. return head;
  328. }

测试

 

 

 

 

声明:本文内容由网友自发贡献,转载请注明出处:【wpsshop】
推荐阅读
相关标签
  

闽ICP备14008679号