[关闭]
@quinn 2015-03-20T09:36:37.000000Z 字数 11929 阅读 4325

C语言单链表-19个功能函数

数据结构

线性表链接存储(单链表)操作
刚开始学习数据结构,找点题目练手,题目和部分源码参考 http://www.cnblogs.com/lifuqing/archive/2011/08/20/list.html
注意问题:
1. 采用vs2012开发,由于vs不支持C99标准,因此申明变量必须位于运算语句之前
2. 链表没有设置头结点(第一个结点包含元素值)
3. 对链表指针的编写有些混乱(如有的 Node* L, 有的用Node** ),注意区分
4. 链表的排序没能编写成功,(后续应多联系链表,并着重学习一下排序)

  1. /************************************************************************/
  2. /* 以下是关于线性表链接存储(单链表)操作的18种算法 */
  3. /* 1.初始化线性表,即置单链表的表头指针为空 */
  4. /* 2.创建线性表,此函数输入负数终止读取数据*/
  5. /* 3.打印链表,链表的遍历*/
  6. /* 4.清除线性表L中的所有元素,即释放单链表L中所有的结点,使之成为一个空表 */
  7. /* 5.返回单链表的长度 */
  8. /* 6.检查单链表是否为空,若为空则返回1,否则返回0 */
  9. /* 7.返回单链表中第pos个结点中的元素,若pos超出范围,则停止程序运行 */
  10. /* 8.从单链表中查找具有给定值x的第一个元素,若查找成功则返回该结点data域的存储地址,否则返回NULL */
  11. /* 9.把单链表中第pos个结点的值修改为x的值,若修改成功返回1,否则返回0 */
  12. /* 10.向单链表的表头插入一个元素 */
  13. /* 11.向单链表的末尾添加一个元素 */
  14. /* 12.向单链表中第pos个结点位置插入元素为x的结点,若插入成功返回1,否则返回0 */
  15. /* 13.向有序单链表中插入元素x结点,使得插入后仍然有序 */
  16. /* 14.从单链表中删除表头结点,并把该结点的值返回,若删除失败则停止程序运行 */
  17. /* 15.从单链表中删除表尾结点并返回它的值,若删除失败则停止程序运行 */
  18. /* 16.从单链表中删除第pos个结点并返回它的值,若删除失败则停止程序运行 */
  19. /* 17.从单链表中删除值为x的第一个结点,若删除成功则返回1,否则返回0 */
  20. /* 18.交换2个元素的位置 */
  21. /* 19.将线性表进行快速排序 */

list_link.h

  1. #ifndef LINK_LIST_H
  2. #define LINK_LIST_H
  3. #include<stdlib.h>
  4. #include <string.h>
  5. #include <stdio.h>
  6. typedef int elemType;
  7. typedef struct Node
  8. {
  9. elemType element;
  10. struct Node *next;
  11. } Node;
  12. void init_list(Node *L);
  13. Node * creat_list();
  14. int print_list(Node *L);
  15. Node * clear_list(Node *L);
  16. int length_list(Node *L);
  17. int isEmpty_list(Node *L);
  18. elemType get_pos_element(Node *L, int pos);
  19. Node* get_pos_prev_address(Node *L, int pos);
  20. Node *get_element_position(Node* L, elemType x);
  21. Node *get_element_prev_position(Node* L, elemType x);
  22. int modify_element(Node* L, int pos, elemType x);
  23. void insert_head_node(Node **L, elemType x);
  24. void insert_end_node(Node **L, elemType x);
  25. int insert_pos_list(Node **L, int pos, elemType x);
  26. int insert_element_to_sorted_list(Node **L, elemType x);
  27. elemType delete_head_node(Node **L);
  28. elemType delete_end_node(Node **L);
  29. elemType delete_pos_node(Node **L, int pos);
  30. int delete_element_node(Node **L, elemType x);
  31. void swap_element_position(Node**L, elemType x, elemType y);
  32. int sort_list(Node **L);
  33. #endif // LINK_LIST_H

link_list.c

  1. #include "link_list.h"
  2. /* 1.初始化线性表,即置单链表的表头指针为空 */
  3. void init_list(Node * L)
  4. {
  5. L = NULL;
  6. printf("初始化链表成功!\n");
  7. }
  8. /* 2.创建线性表,此函数输入负数终止读取数据*/
  9. Node * creat_list()
  10. {
  11. Node * L = NULL;
  12. Node *p1, *p2;
  13. p1 = ( Node *)malloc(sizeof(struct Node));
  14. p2 = ( Node *)malloc(sizeof(struct Node));
  15. if(p1 == NULL || p2 == NULL)
  16. {
  17. printf("内存分配失败!\n");
  18. exit(0);
  19. system("pause");
  20. }
  21. memset(p1, 0, sizeof(struct Node));
  22. printf("请输入链表元素的值:");
  23. scanf("%d",&(p1->element));
  24. p1->next = NULL;
  25. //while(p1->element > 0)
  26. while(p1->element > 0)
  27. {
  28. if( L == NULL)
  29. {
  30. L = p1;
  31. }
  32. else
  33. {
  34. p2->next = p1;
  35. }
  36. p2 = p1;
  37. p1 = ( Node *)malloc(sizeof(struct Node));
  38. if(p1 == NULL || p2 == NULL)
  39. {
  40. printf("内存分配失败!\n");
  41. exit(0);
  42. system("pause");
  43. }
  44. memset(p1, 0, sizeof(struct Node));
  45. printf("请输入链表元素的值:");
  46. scanf("%d",&(p1->element));
  47. p1->next = NULL;
  48. }
  49. printf("创建链表成功!\n");
  50. return L;
  51. }
  52. /* 3.打印链表,链表的遍历*/
  53. int print_list(Node * L)
  54. {
  55. Node *p = L;
  56. if (NULL == p)
  57. {
  58. printf("print_list:链表为空!\n");
  59. return 0;
  60. }
  61. printf("打印链表如下:\n ");
  62. while (p != NULL)
  63. {
  64. printf("%d, ",p->element);
  65. p = p->next;
  66. }
  67. printf("\n");
  68. return 0;
  69. }
  70. /* 4.清除线性表L中的所有元素,即释放单链表L中所有的结点,使之成为一个空表 */
  71. Node* clear_list(Node *L)
  72. {
  73. Node *p = L;
  74. Node *temp = NULL;
  75. printf("clear_list运行成功!\n");
  76. if (p == NULL)
  77. {
  78. printf("链表为空,不需清空\n");
  79. exit(0);
  80. }
  81. while (p != NULL)
  82. {
  83. temp = p->next;
  84. free(p);
  85. p = temp;
  86. }
  87. L =NULL;
  88. printf("已清空链表!\n");
  89. return L;
  90. }
  91. /* 5.返回单链表的长度 */
  92. int length_list(Node *L)
  93. {
  94. int count = 0;
  95. printf("length_list运行成功!\n");
  96. if (L == NULL)
  97. {
  98. printf("链表为空,长度为0\n");
  99. return 0;
  100. }
  101. while( L != NULL)
  102. {
  103. ++count;
  104. L = L->next;
  105. }
  106. return count;
  107. }
  108. /* 6.检查单链表是否为空,若为空则返回1,否则返回0 */
  109. int isEmpty_list(Node *L)
  110. {
  111. printf("isEmpty_list运行成功!\n");
  112. if (L == NULL)
  113. {
  114. printf("链表为空!\n");
  115. return 1;
  116. }
  117. else
  118. {
  119. printf("链表非空!\n");
  120. return 0;
  121. }
  122. }
  123. /* 7.1 返回单链表中第pos个结点中的元素,若pos超出范围,则停止程序运行 */
  124. elemType get_pos_element( Node *L, int pos )
  125. {
  126. int i = 1;
  127. if (L == NULL)
  128. {
  129. printf("get_pos_element()运行成功,链表为空, 获取元素失败!\n");
  130. system("pause");
  131. exit(0);
  132. }
  133. if (pos < 1)
  134. {
  135. printf("get_pos_element()运行成功,给定节点数非法!\n");
  136. system("pause");
  137. exit(0);
  138. }
  139. while(L != NULL)
  140. {
  141. if ( i == pos)
  142. {
  143. printf("get_pos_element()运行成功,第%d个节点元素为%d!\n", pos, L->element);
  144. return L->element;
  145. }
  146. L = L->next;
  147. ++i;
  148. }
  149. printf("get_pos_element()运行成功,超出查找范围!\n");
  150. system("pause");
  151. exit(0);
  152. }
  153. /* 7.2 返回单链表中第pos个结点的前一个地址,方便在pos位置上插入元素,若pos超出范围,则停止程序运行 */
  154. Node* get_pos_prev_address(Node *L, int pos)
  155. {
  156. Node *prev = NULL;
  157. int i = 1;
  158. if (L == NULL)
  159. {
  160. printf("get_pos_address()运行成功,链表为空, 获取元素失败!\n");
  161. system("pause");
  162. return NULL;
  163. }
  164. if (pos < 1)
  165. {
  166. printf("get_pos_address()运行成功,给定节点数非法, 获取元素失败!\n");
  167. system("pause");
  168. return NULL;
  169. }
  170. while(L != NULL)
  171. {
  172. if ( i == pos)
  173. {
  174. printf("get_pos_address()运行成功,第%d个节点元素前一结点的地址为0x%x!\n", pos, L);
  175. //return L; //若返回L,则方便在pos的后一个位置插入元素
  176. return prev; //返回pos的前一个地址,方便在pos位置上插入元素
  177. }
  178. prev = L;
  179. L = L->next;
  180. ++i;
  181. }
  182. printf("get_pos_address()运行成功,超出查找范围!\n");
  183. system("pause");
  184. return NULL;
  185. }
  186. /* 8.1 从单链表中查找具有给定值x的第一个元素,若查找成功则返回该结点data域的存储地址,否则返回NULL */
  187. Node * get_element_position( Node* L, elemType x )
  188. {
  189. if (L == NULL)
  190. {
  191. printf("get_element_position运行成功,链表为空, 获取元素失败!\n");
  192. system("pause");
  193. exit(0);
  194. }
  195. while (L != NULL)
  196. {
  197. if ( L->element == x)
  198. {
  199. printf("get_element_position运行成功,该链表中元素%d的地址为0x%x\n", x, L);
  200. return L;
  201. }
  202. L = L->next;
  203. }
  204. printf("get_element_position运行成功,该链表不含有元素%d\n",x);
  205. return NULL;
  206. }
  207. /* 8.2 从单链表中查找具有给定值x的第一个元素,若查找成功则返回该结点前一结点data域的存储地址,否则返回NULL */
  208. Node * get_element_prev_position( Node* L, elemType x ) //和8.2程序只有返回值的不同
  209. {
  210. Node *prev = NULL;
  211. if (L == NULL)
  212. {
  213. printf("get_element_prev_position运行成功,链表为空, 获取元素失败!\n");
  214. system("pause");
  215. exit(0);
  216. }
  217. while (L != NULL)
  218. {
  219. if ( L->element == x)
  220. {
  221. printf("get_element_prev_position运行成功,该链表中元素%d前一结点的地址为0x%x\n", x, L);
  222. return prev;
  223. }
  224. prev = L;
  225. L = L->next;
  226. }
  227. printf("get_element_prev_position运行成功,该链表不含有元素%d\n",x);
  228. return NULL;
  229. }
  230. /* 9.把单链表中第pos个结点的值修改为x的值,若修改成功返回1,否则返回0 */
  231. int modify_element(Node* L, int pos, elemType x)
  232. {
  233. int i = 1;
  234. if (L == NULL)
  235. {
  236. printf("modify_element函数运行成功,链表为空, 修改失败!\n");
  237. system("pause");
  238. return 0;
  239. }
  240. if (pos < 1)
  241. {
  242. printf("modify_element函数运行成功,给定节点非法!\n");
  243. system("pause");
  244. return 0;
  245. }
  246. while(L != NULL)
  247. {
  248. if ( i == pos)
  249. {
  250. L->element = x;
  251. printf("modify_element函数运行成功,已更换第%d个节点为 %d!\n", pos, x);
  252. return 1;
  253. }
  254. L = L->next;
  255. ++i;
  256. }
  257. printf("modify_element函数运行成功,超出查找范围!\n");
  258. system("pause");
  259. return 0;
  260. }
  261. /* 10.向单链表的表头插入一个元素 */
  262. void insert_head_node( Node **L, elemType x )
  263. {
  264. Node *insert_node;
  265. insert_node = (Node*)malloc(sizeof(Node));
  266. insert_node->element = x;
  267. insert_node->next = *L;
  268. *L = insert_node;
  269. printf("insert_head_list运行成功,向表头添加元素%d!\n", x);
  270. }
  271. /* 11.向单链表的末尾添加一个元素 */
  272. void insert_end_node(Node **L, elemType x)
  273. {
  274. Node *insert_node, *last = NULL;
  275. Node *p = (*L);
  276. insert_node = (Node*)malloc(sizeof(Node));
  277. while (p != NULL)
  278. {
  279. last = p;
  280. p = p->next;
  281. }
  282. last->next = insert_node;
  283. insert_node->element = x;
  284. insert_node->next = NULL;
  285. printf("insert_end_list运行成功,向末尾添加元素%d!\n", x);
  286. }
  287. /* 12.向单链表中第pos个结点位置插入元素为x的结点,成功返回1, 失败返回0 */
  288. int insert_pos_list(Node **L, int pos, elemType x)
  289. {
  290. Node *insert_node = (Node *)malloc(sizeof(Node));
  291. Node *pos_node = get_pos_prev_address(*L, pos);
  292. if (pos_node == NULL)
  293. {
  294. printf("insert_pos_list已运行,但向第%d个节点处添加元素%d时失败,请查看上述提示\n",pos, x);
  295. return 0;
  296. }
  297. insert_node->element = x;
  298. insert_node->next = pos_node->next;
  299. pos_node->next = insert_node;
  300. printf("insert_pos_list运行,向第%d个节点处添加元素%d 成功!\n", pos, x);
  301. return 1;
  302. }
  303. /* 13.向有序单链表中插入元素x结点,使得插入后仍然有序 */
  304. int insert_element_to_sorted_list(Node **L, elemType x)
  305. {
  306. int sort_type = 0; //升序排列为1,降序为0
  307. int ret = 1; //标志位,判断是否为异常情况
  308. elemType first;
  309. Node *p = *L;
  310. Node *left = NULL, *right = NULL, *temp = NULL;
  311. Node *insert_node = (Node *)malloc(sizeof(Node));
  312. insert_node->element = x;
  313. if (p == NULL)
  314. {
  315. printf("insert_element_to_sorted_list运行,链表为空,插入失败\n");
  316. return 0;
  317. }
  318. if ( p->next == NULL) //只有一个元素时
  319. {
  320. printf("insert_element_to_sorted_list运行,链表只有一个元素,插入成功\n");
  321. insert_head_node(L, x);
  322. return 1;
  323. }
  324. first = p->element;
  325. if (p->element >= p->next->element) //根据1st >= 2nd 降序
  326. {
  327. sort_type = 1;
  328. }
  329. //降序时x>=max, 升序时x <= min 应该将x插入表头
  330. if (sort_type && (x >= first))
  331. {
  332. insert_head_node(L, x);
  333. ret = 0; //标志位置0,跳过while
  334. }
  335. if ( (!sort_type) && x <= first)
  336. {
  337. insert_head_node(L, x);
  338. ret = 0; //标志位置0,跳过while
  339. }
  340. while(ret && p != NULL)
  341. {
  342. //升序排列时,right首先非0
  343. if(x < p->element )
  344. right = p;
  345. else
  346. left = p;
  347. // x 左右一大一小时,插入x
  348. if (left != NULL && right != NULL)
  349. {
  350. if (sort_type) //降序,right在insert_node前面,left在后;
  351. {
  352. insert_node->next = right->next;
  353. right->next = insert_node;
  354. }
  355. else //升序,left在前,right在后
  356. {
  357. insert_node->next = left->next;
  358. left->next = insert_node;
  359. }
  360. break;//插入成功,跳出循环
  361. }
  362. p = p->next;
  363. } //while
  364. //降序时x<min, 升序时x > max 应该将x插入表尾
  365. if (p == NULL)
  366. {
  367. insert_end_node(L, x);
  368. }
  369. printf("insert_element_to_sorted_list运行,插入元素%d成功\n",x);
  370. return 1;
  371. }
  372. /* 14.从单链表中删除表头结点,并把该结点的值返回,若删除失败则停止程序运行 */
  373. elemType delete_head_node(Node **L)
  374. {
  375. elemType head_element;
  376. Node *head = NULL;
  377. if(*L == NULL)
  378. {
  379. printf("delete_head_node执行,此链表为空,删除失败, 程序将终止运行\n");
  380. system("pause");
  381. exit(0);
  382. }
  383. head = *L;
  384. head_element = head->element;
  385. *L = head->next;
  386. free(head);
  387. printf("delete_head_node执行,删除表头结点元素%d 成功\n",head_element);
  388. return head_element;
  389. }
  390. /* 15.从单链表中删除表尾结点并返回它的值,若删除失败则停止程序运行 */
  391. elemType delete_end_node(Node **L)
  392. {
  393. elemType end_element;
  394. Node *p = *L, *prev = NULL;
  395. if(p == NULL)
  396. {
  397. printf("delete_end_node执行,此链表为空,删除失败, 程序将终止运行\n");
  398. system("pause");
  399. exit(0);
  400. }
  401. while(p->next != NULL)
  402. {
  403. prev = p;
  404. p = p->next;
  405. }
  406. end_element = p->element;
  407. if ( prev != NULL)//链表只有一个元素时,prev == NULL
  408. {
  409. prev->next = NULL;
  410. }
  411. else
  412. *L = NULL; //只有一个元素,将表头置空
  413. free(p);
  414. printf("delete_end_node执行,删除表尾结点元素%d 成功\n",end_element);
  415. return end_element;
  416. }
  417. /* 16.从单链表中删除第pos个结点并返回它的值,若删除失败则停止程序运行 */
  418. elemType delete_pos_node(Node **L, int pos)
  419. {
  420. elemType delete_node_element;
  421. Node *delete_node = NULL;
  422. Node *pos_prev_node = NULL;
  423. if(*L == NULL)
  424. {
  425. printf("delete_pos_node执行,此链表为空,删除失败, 程序将终止运行\n");
  426. system("pause");
  427. exit(0);
  428. }
  429. pos_prev_node = get_pos_prev_address(*L, pos);
  430. if(pos_prev_node == NULL)
  431. {
  432. printf("delete_pos_node执行,查找第%d个结点失败,删除失败, 程序将终止运行\n", pos);
  433. exit(0);
  434. }
  435. delete_node = pos_prev_node->next;
  436. pos_prev_node->next = delete_node->next;
  437. delete_node_element = delete_node->element;
  438. free(delete_node);
  439. printf("delete_pos_node执行,删除第%d个结点(其元素值为%d)成功, 程序将终止运行\n", pos, delete_node_element);
  440. return delete_node_element;
  441. }
  442. /* 17.从单链表中删除值为x的第一个结点,若删除成功则返回1,否则返回0 */
  443. int delete_element_node(Node **L, elemType x)
  444. {
  445. Node *delete_node = NULL;
  446. Node *x_prev_node = NULL;
  447. if(*L == NULL)
  448. {
  449. printf("delete_pos_node执行,此链表为空,删除失败\n");
  450. return 0;
  451. }
  452. x_prev_node = get_element_prev_position(*L, x);
  453. if(x_prev_node == NULL)
  454. {
  455. printf("delete_element_node执行,查找结点元素%d失败,删除失败\n", x);
  456. return 0;
  457. }
  458. delete_node = x_prev_node->next;
  459. x_prev_node->next = delete_node->next;
  460. free(delete_node);
  461. printf("delete_element_node执行,删除元素值为%d的结点成功, 程序将终止运行\n", x);
  462. return 1;
  463. }
  464. /* 18.交换2个元素的位置 */
  465. void swap_element_position(Node**L, elemType x, elemType y)
  466. {
  467. Node *x_prev_node = NULL, *y_prev_node = NULL, *x_node = NULL, *y_node = NULL, *temp = NULL;
  468. Node *head = NULL;
  469. elemType first = (*L)->element;
  470. if ( *L ==NULL )
  471. {
  472. printf("swap_element_position运行,链表为空,终止运行\n");
  473. }
  474. /*===由于采用返回查找元素前一结点的地址,因此表头节点需要单独考虑===*/
  475. if ( first ==x )
  476. {
  477. y_prev_node = get_element_prev_position(*L, y);
  478. y_node = y_prev_node->next;
  479. x_node = *L;
  480. temp = y_node->next;
  481. y_prev_node->next = x_node;
  482. y_node->next = x_node->next;
  483. *L = y_node;
  484. x_node->next = temp;
  485. }
  486. else if( first == y)
  487. {
  488. x_prev_node = get_element_prev_position(*L, x);
  489. x_node = x_prev_node->next;
  490. y_node = *L;
  491. temp = x_node->next;
  492. x_prev_node->next = y_node;
  493. x_node->next = y_node->next;
  494. *L = x_node;
  495. y_node->next = temp;
  496. }
  497. else //一般情况,x, y 都不在表头
  498. {
  499. x_prev_node = get_element_prev_position(*L, x);
  500. y_prev_node = get_element_prev_position(*L, y);
  501. if (x_prev_node != NULL && y_prev_node != NULL) //画出结点连接图,易懂
  502. {
  503. y_node = y_prev_node->next;
  504. x_node = x_prev_node->next;
  505. temp = y_node->next;
  506. y_prev_node->next = x_node;
  507. y_node->next = x_node->next;
  508. x_prev_node->next = y_node;
  509. x_node->next = temp;
  510. }
  511. }
  512. printf("交换元素%d和%d成功!\n", x, y);
  513. }
  514. /* 19.将线性表进行快速排序 */
  515. int sort_list(Node **L) //有错误,仍需修改
  516. {
  517. Node *x = NULL, *y = NULL;
  518. Node *p = NULL, *f = NULL, *head = *L;
  519. if ( p == NULL || p->next == NULL)
  520. {
  521. }
  522. f = NULL;
  523. //判断是否只有一个元素或者没有元素
  524. if(head == NULL || head -> next == NULL)
  525. {
  526. printf("sort_list运行,链表为空or只有一个元素,终止运行\n");
  527. return;
  528. }
  529. while(f != head->next)
  530. {
  531. for(p = head; p -> next -> next != f; p = p -> next)
  532. {
  533. if(p -> next -> element > p -> next -> next ->element)
  534. {
  535. x = p -> next;
  536. y = p -> next -> next;
  537. p -> next = y;
  538. x -> next = y -> next;
  539. y -> next = x;
  540. }
  541. }
  542. f = p -> next;
  543. }
  544. //*L = p;
  545. printf("升序排列完成\n");
  546. }

main.c

  1. #include "link_list.h"
  2. int main()
  3. {
  4. int n;
  5. Node * L = NULL;
  6. Node *p = NULL;
  7. init_list(L);
  8. length_list(L);
  9. isEmpty_list(L);
  10. L = creat_list();
  11. length_list(L);
  12. insert_element_to_sorted_list(&L, 5);
  13. print_list(L);
  14. swap_element_position(&L, 2, 5);
  15. print_list(L);
  16. sort_list(&L);
  17. print_list(L);
  18. delete_element_node(&L, 3);
  19. print_list(L);
  20. delete_pos_node(&L, 2);
  21. print_list(L);
  22. delete_head_node(&L);
  23. print_list(L);
  24. delete_end_node(&L);
  25. print_list(L);
  26. insert_head_node(&L, 200);
  27. insert_end_node(&L, 400);
  28. print_list(L);
  29. insert_pos_list(&L, 2, 50);
  30. insert_pos_list(&L, 6, 40);
  31. print_list(L);
  32. n = get_pos_element(L, 3);
  33. printf("第3个元素为%d\n",n);
  34. modify_element(L, 3, 100);
  35. print_list(L);
  36. modify_element(L, 5, 100);
  37. print_list(L);
  38. modify_element(L, 0, 100);
  39. print_list(L);
  40. p = get_element_position(L, 3);
  41. printf("元素3的地址:%x\n",p);
  42. p = get_element_position(L, 10);
  43. printf("元素10的地址:%x\n",p);
  44. isEmpty_list(L);
  45. n = length_list(L);
  46. printf("链表长度为:%d\n", n);
  47. print_list(L);
  48. L = clear_list(L);
  49. system("pause");
  50. return 0;
  51. }

在此输入正文

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注