【数据结构】高效双向链表list、树tree(二叉树)

vi正常模式下:
"shift + g" 跳到最后一行
"gg" 跳到第一行

<效率更高的双向链表结构代码>

 
  1. /*代码*/ 01link.c

  2. #include <stdlib.h>

  3. #include "01link.h"

  4. //链表初始化

  5. void link_init(Link *p_link) {

  6. p_link->head.p_next = &(p_link->tail);

  7. p_link->tail.p_prev = &(p_link->head);

  8. p_link->tail.p_next = NULL;

  9. p_link->head.p_prev = NULL;

  10. p_link->p_cur = NULL;

  11. }

  12. //链表清理

  13. void link_deinit(Link *p_link) {

  14. while(p_link->head.p_next != &(p_link->tail)) {

  15. Node *p_first = &(p_link->head);

  16. Node *p_mid = p_first->p_next;

  17. Node *p_last = p_mid->p_next;

  18. p_first->p_next = p_last;

  19. p_last->p_prev = p_first;

  20. free(p_mid);

  21. p_mid = NULL;

  22. }

  23. p_link->p_cur = NULL;

  24. }

  25. //统计有效节点数据个数

  26. int link_size(const Link *p_link) {

  27. int cnt = 0;

  28. const Node *p_node = NULL;

  29. for(p_node = &(p_link->head); p_node != &(p_link->tail); p_node = p_node->p_next) {

  30. const Node *p_first = p_node;

  31. const Node *p_mid = p_first->p_next;

  32. const Node *p_last = p_mid->p_next;

  33. cnt++;

  34. }

  35. return cnt - 1;

  36. }

  37. //把新数字加入到最前面,num代表要加入的数字

  38. void link_add_head(Link *p_link, int num) {

  39. Node *p_first = NULL, *p_mid = NULL, *p_last = NULL;

  40. Node *p_node = (Node *)malloc(sizeof(Node));

  41. if(!p_node) {

  42. return ;

  43. }

  44. p_node->num = num;

  45. p_node->p_next = NULL;

  46. p_node->p_prev = NULL;

  47. p_first = &(p_link->head);

  48. p_mid = p_first->p_next;

  49. p_last = p_mid->p_next;

  50. p_first->p_next = p_node;

  51. p_node->p_prev = p_first;

  52. p_node->p_next = p_mid;

  53. p_mid->p_prev = p_node;

  54. p_link->p_cur = NULL;

  55. }

  56. //把新数字加入到最后面(追加),num代表要加入的数字

  57. void link_append(Link *p_link, int num) {

  58. Node *p_tmp = NULL; //循环指针变量

  59. Node *p_node = (Node *)malloc(sizeof(Node));

  60. if(!p_node) {

  61. return ;

  62. }

  63. p_node->num = num;

  64. p_node->p_next = NULL;

  65. p_node->p_prev = NULL;

  66. for(p_tmp = &(p_link->head); p_tmp != &(p_link->tail); p_tmp = p_tmp->p_next) {

  67. Node *p_first = p_tmp;

  68. Node *p_mid = p_first->p_next;

  69. Node *p_last = p_mid->p_next;

  70. if(p_mid == &(p_link->tail)) {

  71. p_first->p_next = p_node;

  72. p_node->p_prev = p_first;

  73. p_node->p_next = p_mid;

  74. p_mid->p_prev = p_node;

  75. break;

  76. }

  77. }

  78. p_link->p_cur = NULL;

  79. }

  80. //按顺序加入新数字

  81. void link_insert_in_order(Link *p_link, int num) {

  82. Node *p_tmp = NULL;

  83. Node *p_node = (Node *)malloc(sizeof(Node));

  84. if(!p_node) {

  85. return ;

  86. }

  87. p_node->num = num;

  88. p_node->p_next = NULL;

  89. p_node->p_prev = NULL;

  90. for(p_tmp = &(p_link->head); p_tmp != &(p_link->tail); p_tmp = p_tmp->p_next) {

  91. Node *p_first = p_tmp;

  92. Node *p_mid = p_first->p_next;

  93. Node *p_last = p_mid->p_next;

  94. if(p_mid == &(p_link->tail) || p_mid->num > num) {

  95. p_first->p_next = p_node;

  96. p_node->p_prev = p_first;

  97. p_node->p_next = p_mid;

  98. p_mid->p_prev = p_node;

  99. break;

  100. }

  101. }

  102. p_link->p_cur = NULL;

  103. }

  104. //删除最前面数字的函数

  105. void link_remove_head(Link *p_link) {

  106. Node *p_first = &(p_link->head);

  107. Node *p_mid = p_first->p_next;

  108. Node *p_last = p_mid->p_next;

  109. if(p_mid == &(p_link->tail)) {

  110. return ;

  111. }

  112. p_first->p_next = p_last;

  113. p_last->p_prev = p_first;

  114. free(p_mid);

  115. p_mid = NULL;

  116. p_link->p_cur = NULL;

  117. }

  118. //删除最后一个数字的函数

  119. void link_remove_tail(Link *p_link) {

  120. Node *p_node = NULL;

  121. for(p_node = &(p_link->head); p_node != &(p_link->tail); p_node = p_node->p_next) {

  122. Node *p_first = p_node;

  123. Node *p_mid = p_first->p_next;

  124. Node *p_last = p_mid->p_next;

  125. if(p_last == &(p_link->tail)) {

  126. p_first->p_next = p_last;

  127. p_last->p_prev = p_first;

  128. free(p_mid);

  129. p_mid = NULL;

  130. break;

  131. }

  132. }

  133. p_link->p_cur = NULL;

  134. }

  135. //删除某个数字的函数

  136. void link_remove(Link *p_link, int num) {

  137. Node *p_node = NULL;

  138. for(p_node = &(p_link->head); p_node != &(p_link->tail); p_node = p_node->p_next) {

  139. Node *p_first = p_node;

  140. Node *p_mid = p_first->p_next;

  141. Node *p_last = p_mid->p_next;

  142. if(p_mid != &(p_link->tail) && p_mid->num == num) {

  143. p_first->p_next = p_last;

  144. p_last->p_prev = p_first;

  145. free(p_mid);

  146. p_mid = NULL;

  147. break;

  148. }

  149. }

  150. p_link->p_cur = NULL;

  151. }

  152. //获得第一个数字的函数

  153. int link_get_head(const Link *p_link, int *p_num) {

  154. if(p_link->head.p_next == &(p_link->tail)) {

  155. return 0;

  156. }

  157. else {

  158. *p_num = p_link->head.p_next->num;

  159. return 1;

  160. }

  161. }

  162. //获得最后一个数字的函数

  163. int link_get_tail(const Link *p_link, int *p_num) {

  164. const Node *p_node = NULL;

  165. if(p_link->head.p_next == &(p_link->tail)) {

  166. return 0;

  167. }

  168. for(p_node = &(p_link->head); p_node != &(p_link->tail); p_node = p_node->p_next) {

  169. const Node *p_first = p_node;

  170. const Node *p_mid = p_first->p_next;

  171. const Node *p_last = p_mid->p_next;

  172. if(p_last == &(p_link->tail)) {

  173. *p_num = p_mid->num;

  174. return 1;

  175. }

  176. }

  177. }

  178. //获得某个编号的数字的函数,num表示编号,*p_num获得的数字

  179. int link_get(const Link *p_link, int num, int *p_num) {

  180. int cnt = 0;

  181. const Node *p_node = NULL;

  182. for(p_node = &(p_link->head); p_node != &(p_link->tail); p_node = p_node->p_next) {

  183. const Node *p_first = p_node;

  184. const Node *p_mid = p_first->p_next;

  185. const Node *p_last = p_mid->p_next;

  186. if(p_mid != &(p_link->tail) && cnt == num) {

  187. *p_num = p_mid->num;

  188. return 1;

  189. }

  190. cnt++;

  191. }

  192. return 0;

  193. }

  194. //开始从前向后遍历(准备开始调用link_add_head函数)

  195. void link_begin(Link *p_link) {

  196. p_link->p_cur = &(p_link->head);

  197. }

  198. //在从前向后的遍历过程中获得下一个数字

  199. int link_next(Link *p_link, int *p_num) {

  200. //如果指针是空就表示没有数据

  201. if(!(p_link->p_cur)) {

  202. return 0;

  203. }

  204. p_link->p_cur = p_link->p_cur->p_next; //指针向后移动一步

  205. if(p_link->p_cur == &(p_link->tail)) { //指针和尾节点捆绑

  206. p_link->p_cur = NULL; //指针恢复到开始之前的样子

  207. return 0;

  208. }

  209. else {

  210. *p_num = p_link->p_cur->num; //指针有效节点捆绑

  211. return 1;

  212. }

  213. }

  214. //开始从后向前遍历

  215. void link_rbegin(Link *p_link) {

  216. p_link->p_cur = &(p_link->tail);

  217. }

  218. //在从后向前的遍历过程中获得下一个数字

  219. int link_prev(Link *p_link, int *p_num) {

  220. if(!(p_link->p_cur)) {

  221. return 0;

  222. }

  223. p_link->p_cur = p_link->p_cur->p_prev; //指针向前移动一步

  224. if(p_link->p_cur == &(p_link->head)) {

  225. p_link->p_cur = NULL;

  226. return 0;

  227. }

  228. else {

  229. *p_num = p_link->p_cur->num;

  230. return 1;

  231. }

  232. }

  233.  
  234.  
  235. /*代码*/ 01link.h

  236. #ifndef __01LINK_H__

  237. #define __01LINK_H__

  238.  
  239.  
  240. #include <stdlib.h>

  241. typedef struct Node{

  242. int num;

  243. struct Node *p_next;

  244. struct Node *p_prev; //prev:上一个

  245. } Node;

  246. typedef struct {

  247. Node head, tail;

  248. Node *p_cur; //随着函数调用,该指针依次和每个数字捆绑

  249. } Link;

  250. void link_init(Link *); //链表初始化

  251. void link_deinit(Link *); //链表清理

  252. int link_size(const Link *); //统计有效节点数据个数

  253. //把新数字加入到最前面,num代表要加入的数字

  254. void link_add_head(Link *, int);

  255. //把新数字加入到最后面(追加),num代表要加入的数字

  256. void link_append(Link *, int);

  257. //按顺序加入新数字

  258. void link_insert_in_order(Link *, int);

  259. //删除最前面数字的函数

  260. void link_remove_head(Link *);

  261. //删除最后一个数字的函数

  262. void link_remove_tail(Link *);

  263. //删除某个数字的函数

  264. void link_remove(Link *, int);

  265. //获得第一个数字的函数

  266. int link_get_head(const Link *, int *);

  267. //获得最后一个数字的函数

  268. int link_get_tail(const Link *, int *);

  269. //获得某个编号的数字的函数,num表示编号,*p_num获得的数字

  270. int link_get(const Link *, int, int *);

  271. //开始从前向后遍历的函数

  272. void link_begin(Link *);

  273. //在从前向后的遍历中获得下一个数字的函数

  274. int link_next(Link *, int *);

  275. //在从后向前遍历的函数

  276. void link_rbegin(Link *);

  277. //在从后向前的遍历过程中获得下一个数字

  278. int link_prev(Link *, int *);

  279.  
  280.  
  281. #endif //__01LINK_H__

  282.  
  283.  
  284. /*代码*/ 01main.c

  285. #include <stdio.h>

  286. #include "01link.h"

  287. int main() {

  288. int num = 0;

  289. Link lnk = {0};

  290. link_init(&lnk);

  291. link_append(&lnk, 3);

  292. link_append(&lnk, 5);

  293. link_append(&lnk, 7);

  294. link_append(&lnk, 9);

  295. link_append(&lnk, 11);

  296. link_begin(&lnk);

  297. while(1) {

  298. if(!link_next(&lnk, &num)) { //如果没拿到数字

  299. break;

  300. }

  301. printf("%d ", num);

  302. }

  303. printf("\n");

  304. link_rbegin(&lnk);

  305. while(1) {

  306. if(!link_prev(&lnk, &num)) {

  307. break;

  308. }

  309. printf("%d ", num);

  310. }

  311. printf("\n");

  312. link_deinit(&lnk);

  313. return 0;

  314. }


【树】
如果单向线性链式物理结构中每个节点可以向后找到多个其他节点,就成为了一棵"树"
树里的节点可以分成几层,"不同层之间符合线性规律"(任何两层之间都有前后顺序)
树的最上面一层只有一个节点,这个节点叫做"树的根节点"
可以"用根节点代表整棵树"
如果树中两个节点之间有直接的联系,就说明他们之间存在"父子关系"
靠近根节点的叫"父节点",远离根节点的叫"子节点"
任何节点"最多只能有一个父节点",但是"可以有多个子节点"

【二叉树】
如果每个节点"最多只有两个"子节点,就把这种树叫做"二叉树"
二叉树是最简单的树(所有的树都可以转化为二叉树)
二叉树里"用左右区分"一个节点的两个不同子节点
二叉树里任何一个节点都可以看作是一个二叉树的根节点
如果二叉树中一个节点叫 A ,它的左子节点叫 B 右子节点叫 C,则B所代表的二叉树叫做A的"左子树",C所代表的二叉树叫做A的"右子树"

树的遍历指的是:"依次处理树里的每一个节点"
树的大多数操作都是通过遍历实现的
通常采用"递归方式解决树的遍历"问题
在对树进行遍历的时候,一定"先遍历左"子树,然"后遍历右"子树
如果最先处理根节点叫做"前序遍历"
如果中间处理根节点叫做"中序遍历"
如果最后处理根节点叫做"后序遍历"

【练习】
编写函数计算一棵树的高度

 
  1. /*代码*/ 01tree.h 头文件

  2. #ifndef __01TREE_H__

  3. #define __01TREE_H__

  4. struct node;

  5. typedef struct {

  6. struct node *p_node;

  7. } tree;

  8. typedef struct node {

  9. int num;

  10. tree left;

  11. tree right;

  12. } node;

  13. //树的初始化函数

  14. void tree_init(tree *);

  15. //树的清理函数

  16. void tree_deinit(tree *);

  17. //按顺序在树里插入新数字

  18. void tree_insert_in_order(tree *, int );

  19. //中序遍历函数

  20. void miter(tree *, void (*)(int));

  21. //前序遍历函数

  22. void fiter(tree *, void (*)(int));

  23. //后序遍历函数

  24. void liter(tree *, void (*)(int));

  25. //删除节点的函数

  26. void tree_remove(tree *, int );

  27. //计算树高度的函数

  28. int tree_height(const tree *);

  29. #endif //__01TREE_H__

  30.  
  31. /*代码*/ 01tree.c 函数源文件

  32. #include <stdlib.h>

  33. #include "01tree.h"

  34. //树的初始化函数

  35. void tree_init(tree *p_tree) {

  36. p_tree->p_node = NULL;

  37. }

  38. //树的清理函数

  39. void tree_deinit(tree *p_tree) {

  40. if (!p_tree->p_node) {

  41. return ;

  42. }

  43. tree_deinit(&(p_tree->p_node->left));

  44. tree_deinit(&(p_tree->p_node->right));

  45. free(p_tree->p_node);

  46. p_tree->p_node = NULL;

  47. }

  48. //在有序二叉树里查找某个数字所在的位置

  49. const tree *tree_search_in_order(const tree *p_tree, int num) {

  50. if (!p_tree->p_node) {

  51. return p_tree;

  52. }

  53. if (p_tree->p_node->num == num) {

  54. return p_tree;

  55. }

  56. else if (p_tree->p_node->num > num) {

  57. return tree_search_in_order(&(p_tree->p_node->left), num);

  58. }

  59. else {

  60. return tree_search_in_order(&(p_tree->p_node->right), num);

  61. }

  62. }

  63. //按顺序向有序二叉树中插入新数字

  64. void tree_insert_in_order(tree *p_tree, int num) {

  65. tree *p_tmp = (tree *)tree_search_in_order(p_tree, num);

  66. if (!p_tmp->p_node) {

  67. node *p_node = (node *)malloc(sizeof(node));

  68. if (p_node) {

  69. p_node->num = num;

  70. p_node->left.p_node = NULL;

  71. p_node->right.p_node = NULL;

  72. p_tmp->p_node = p_node;

  73. }

  74. }

  75. }

  76. //按顺序把有序二叉树里所有数字显示

  77. //在屏幕上

  78. /*void tree_print(tree *p_tree) {

  79. if (!p_tree->p_node) {

  80. return ;

  81. }

  82. tree_print(&(p_tree->p_node->left));

  83. printf("%d ", p_tree->p_node->num);

  84. tree_print(&(p_tree->p_node->right));

  85. }*/

  86. //中序遍历函数

  87. void miter(tree *p_tree, void (*p_func)(int)) {

  88. if (!p_tree->p_node) {

  89. return ;

  90. }

  91. miter(&(p_tree->p_node->left), p_func);

  92. p_func(p_tree->p_node->num);

  93. miter(&(p_tree->p_node->right), p_func);

  94. }

  95. //前序遍历函数

  96. void fiter(tree *p_tree, void (*p_func)(int)) {

  97. if (!p_tree->p_node) {

  98. return ;

  99. }

  100. p_func(p_tree->p_node->num);

  101. miter(&(p_tree->p_node->left), p_func);

  102. miter(&(p_tree->p_node->right), p_func);

  103. }

  104. //后序遍历函数

  105. void liter(tree *p_tree, void (*p_func)(int)) {

  106. if (!p_tree->p_node) {

  107. return ;

  108. }

  109. miter(&(p_tree->p_node->left), p_func);

  110. miter(&(p_tree->p_node->right), p_func);

  111. p_func(p_tree->p_node->num);

  112. }

  113. //删除节点的函数

  114. void tree_remove(tree *p_tree, int num) {

  115. node *p_node = NULL;

  116. tree *p_tmp = (tree *)tree_search_in_order(p_tree, num);

  117. if (!p_tmp->p_node) {

  118. return ;

  119. }

  120. p_node = p_tmp->p_node;

  121. if (!p_tmp->p_node->left.p_node) {

  122. p_tmp->p_node = p_tmp->p_node->right.p_node;

  123. }

  124. else if (!p_tmp->p_node->right.p_node) {

  125. p_tmp->p_node = p_tmp->p_node->left.p_node;

  126. }

  127. else {

  128. tree *p_tmp1 = (tree *)tree_search_in_order(&(p_tmp->p_node->left), p_tmp->p_node->right.p_node->num);

  129. p_tmp1->p_node = p_tmp->p_node->right.p_node;

  130. p_tmp->p_node = p_tmp->p_node->left.p_node;

  131. }

  132. free(p_node);

  133. p_node = NULL;

  134. }

  135. //计算树高度的函数

  136. int tree_height(const tree *p_tree) {

  137. int ret = 0, left_height = 0, right_height = 0;

  138. if (!p_tree->p_node) {

  139. return 0;

  140. }

  141. left_height = tree_height(&(p_tree->p_node->left));

  142. right_height = tree_height(&(p_tree->p_node->right));

  143. ret = left_height > right_height ? left_height : right_height;

  144. return ret + 1;

  145. }

  146.  
  147.  
  148. /*代码*/ 01main.c 树的主函数

  149. #include <stdio.h>

  150. #include "01tree.h"

  151. void print(int num) {

  152. printf("%d ", num);

  153. }

  154. int main() {

  155. tree tr = {0};

  156. tree_init(&tr);

  157. tree_insert_in_order(&tr, 50);

  158. tree_insert_in_order(&tr, 30);

  159. tree_insert_in_order(&tr, 70);

  160. tree_insert_in_order(&tr, 15);

  161. tree_insert_in_order(&tr, 40);

  162. tree_insert_in_order(&tr, 60);

  163. tree_insert_in_order(&tr, 80);

  164. tree_insert_in_order(&tr, 7);

  165. tree_insert_in_order(&tr, 21);

  166. tree_insert_in_order(&tr, 100);

  167. printf("树的高度是%d\n", tree_height(&tr));//树的高度是4

  168. miter(&tr, print); //7 15 21 30 40 50 60 70 80 100

  169. printf("\n");

  170. tree_remove(&tr, 30);

  171. miter(&tr, print); //7 15 21 40 50 60 70 80 100

  172. printf("\n");

  173. tree_deinit(&tr);

  174. return 0;

  175. }

猜你喜欢

转载自blog.csdn.net/wlf_go/article/details/81906419
今日推荐