当前位置:   article > 正文

数据结构——二叉树 C语言代码实现(可直接运行)_数据结构二叉树代码实现

数据结构二叉树代码实现

 原理见另一篇文章数据结构——二叉树 原理

1. 接口实现

  1. #pragma once
  2. #include<stdio.h>
  3. #include<stdlib.h>
  4. #include<assert.h>
  5. #include<stdbool.h>
  6. #include<time.h>
  7. typedef int HPDataType;
  8. typedef struct Heap
  9. {
  10. HPDataType* a;
  11. int size;
  12. int capacity;
  13. }HP;
  14. void HeapInit(HP* php); // 初始化
  15. void HeapDestroy(HP* php); // 清空
  16. void Swap(HPDataType* p1, HPDataType* p2);
  17. void AdjustUp(HPDataType* a, int child); // 向上传递
  18. void AdjustDown(HPDataType* a, int size, int parent);
  19. void HeapPush(HP* php, HPDataType x); // 插入新元素
  20. void HeapPop(HP* php); // 删除根数据
  21. HPDataType HeapTop(HP* php); // 获取栈顶元素
  22. size_t HeapSize(HP* php);
  23. bool HeapEmpty(HP* php);
  24. // 层序遍历用到的部分
  25. // 层序遍历实现的原理是将根节点放入队列,然后出队列,与此同时将他的左孩子和右孩子带入队列
  26. typedef struct BinaryTreeNode* QDataType; //放入队列里的元素是节点而不是节点的值,因为数据类型应该是节点的指针
  27. // 不能用TreeNode*,得放原生类型struct BinaryTreeNode*
  28. typedef struct QueueNode
  29. {
  30. QDataType val;
  31. struct QueueNode* next;
  32. }QNode;
  33. typedef struct Queue
  34. {
  35. QNode* phead; // 头指针
  36. QNode* ptail; // 尾指针
  37. int size;
  38. }Queue;
  39. void QueueInit(Queue* pq);
  40. void QueueDestroy(Queue* pq);
  41. void QueuePush(Queue* pq, QDataType x);
  42. void QueuePop(Queue* pq);
  43. QDataType QueueFront(Queue* pq);
  44. QDataType QueueBack(Queue* pq);
  45. bool QueueEmpty(Queue* pq);
  46. int QueueSize(Queue* pq);

2. 函数实现

  1. #define _CRT_SECURE_NO_WARNINGS 1
  2. #include<stdio.h>
  3. #include"Heap.h"
  4. #include<assert.h>
  5. void HeapInit(HP* php)
  6. {
  7. assert(php);
  8. php->a = NULL;
  9. php->size = 0;
  10. php->capacity = 0;
  11. }
  12. void HeapDestroy(HP* php)
  13. {
  14. assert(php);
  15. free(php->a);
  16. php->a = NULL;
  17. php->size = php->capacity = 0;
  18. }
  19. void Swap(HPDataType* p1, HPDataType* p2)
  20. {
  21. HPDataType tmp = *p1;
  22. *p1 = *p2;
  23. *p2 = tmp;
  24. }
  25. 升序建大堆
  26. //void AdjustUp(HPDataType* a, int child) // 向上调整
  27. //{
  28. // int parent = (child - 1) / 2;
  29. // while (child > 0)
  30. // {
  31. // if (a[child] > a[parent])
  32. // {
  33. // Swap(&a[child], &a[parent]);
  34. // child = parent;
  35. // parent = (parent - 1) / 2;
  36. // }
  37. // else
  38. // {
  39. // break;
  40. // }
  41. // }
  42. //}
  43. //
  44. 升序建大堆
  45. //void AdjustDown(HPDataType* a, int size, int parent) // 向下调整
  46. //{
  47. // // 假设左孩子小,如果不是,更新成右孩子
  48. // int child = parent * 2 + 1;
  49. // while (child < size)
  50. // {
  51. // if (child + 1 < size && a[child + 1] > a[child])
  52. // {
  53. // ++child;
  54. // }
  55. // if (a[child] > a[parent])
  56. // {
  57. // Swap(&a[child], &a[parent]);
  58. // parent = child;
  59. // child = parent * 2 + 1;
  60. // }
  61. // else
  62. // {
  63. // break;
  64. // }
  65. // }
  66. //}
  67. //降序建小堆
  68. void AdjustUp(HPDataType * a, int child) // 向上调整
  69. {
  70. int parent = (child - 1) / 2;
  71. while (child > 0)
  72. {
  73. if (a[child] < a[parent])
  74. {
  75. Swap(&a[child], &a[parent]);
  76. child = parent;
  77. parent = (parent - 1) / 2;
  78. }
  79. else
  80. {
  81. break;
  82. }
  83. }
  84. }
  85. //降序建小堆
  86. void AdjustDown(HPDataType * a, int size, int parent) // 向下调整
  87. {
  88. // 假设左孩子小,如果不是,更新成右孩子
  89. int child = parent * 2 + 1;
  90. while (child < size)
  91. {
  92. if (child + 1 < size && a[child + 1] < a[child])
  93. {
  94. ++child;
  95. }
  96. if (a[child] < a[parent])
  97. {
  98. Swap(&a[child], &a[parent]);
  99. parent = child;
  100. child = parent * 2 + 1;
  101. }
  102. else
  103. {
  104. break;
  105. }
  106. }
  107. }
  108. void HeapPush(HP* php, HPDataType x)
  109. {
  110. //assert(php);
  111. //if (php->size == php->capacity)
  112. //{
  113. // size_t newCapacity = php->capacity == 0 ? 4 : php->capacity * 2;
  114. // HPDataType* tmp = (HPDataType*)realloc(php->a, newCapacity * sizeof(HPDataType));
  115. // if (tmp == NULL)
  116. // {
  117. // perror("realloc fail");
  118. // exit(-1);
  119. // }
  120. // php->a = tmp;
  121. // php->capacity = newCapacity;
  122. //}
  123. //php->a[php->size] = x; // C28182警告
  124. //php->size++;
  125. // 上述代码会有C28182警告的原因在于判断tmp是否为空的时候,使用了exit(-1),
  126. // exit(-1) 被用于处理 realloc 失败的情况。当 realloc 失败时,
  127. // tmp 指针将保持为 NULL,因为 realloc 没有成功分配新的内存。
  128. // 在这种情况下,如果继续执行 php->a[php->size] = x;,
  129. // 就会尝试取消引用一个 NULL 指针,这正是 C28182 警告所指出的问题。
  130. //
  131. // 在下述代码中,return 被用于处理 realloc 失败的情况。
  132. // 这意味着当 realloc 失败时,函数会立即返回,不会执行后续的代码,
  133. // 包括 php->a[php->size] = x;。因此,不会有取消引用 NULL 指针的风险,
  134. // 所以不会触发 C28182 警告。
  135. assert(php);
  136. if (php->size == php->capacity)
  137. {
  138. size_t newcapacity = php->capacity == 0 ? 4 : php->capacity * 2; //如果栈的当前容量为0,将其设为4,否则将其扩大为当前容量的两倍
  139. HPDataType* tmp = (HPDataType*)realloc(php->a, sizeof(HPDataType) * newcapacity);
  140. if (tmp == NULL)
  141. {
  142. perror("realloc fail");
  143. return;
  144. }
  145. php->a = tmp; //将原来栈中数据的指针更新为新的内存空间的指针
  146. php->capacity = newcapacity;
  147. }
  148. php->a[php->size] = x;
  149. php->size++;
  150. AdjustUp(php->a, php->size - 1);
  151. }
  152. void HeapPop(HP* php)
  153. {
  154. assert(php);
  155. assert(php->size > 0);
  156. Swap(&php->a[0], &php->a[php->size]-1);
  157. php->size--;
  158. AdjustDown(php->a, php->size, 0);
  159. }
  160. HPDataType HeapTop(HP* php)
  161. {
  162. assert(php);
  163. assert(php->size > 0);
  164. return php->a[0];
  165. }
  166. size_t HeapSize(HP* php)
  167. {
  168. assert(php);
  169. return php->size;
  170. }
  171. bool HeapEmpty(HP* php)
  172. {
  173. assert(php);
  174. return php->size == 0;
  175. }

3. 调试

  1. #define _CRT_SECURE_NO_WARNINGS 1
  2. #include<stdio.h>
  3. #include"Heap.h"
  4. #include<math.h>
  5. //int main()
  6. //{
  7. // int a[] = { 3,5,7,4,5,7,2,4 };
  8. //
  9. // HP hp;
  10. // HeapInit(&hp);
  11. // for (int i = 0; i < sizeof(a) / sizeof(int); ++i)
  12. // {
  13. // HeapPush(&hp,a[i]);
  14. // }
  15. //
  16. // /*int k = 3;
  17. // while (k--)
  18. // {
  19. // printf("%d\n", HeapTop(&hp));
  20. // HeapPop(&hp);
  21. // }*/
  22. //
  23. // // 排序,每次输出top,然后删除toptop调整为次大/次小
  24. // while (!HeapEmpty(&hp))
  25. // {
  26. // printf("%d ", HeapTop(&hp));
  27. // HeapPop(&hp);
  28. // }
  29. // printf("\n");
  30. //
  31. // return 0;
  32. //}
  33. //void HeapSort(int* a, int n)
  34. //{
  35. // // 建堆,本质是模拟堆插入过程
  36. // // 升序建大堆
  37. // // 降序建小堆
  38. // // O(N*logN)
  39. // /*for (int i = 1; i < n; i++)
  40. // {
  41. // AdjustUp(a, i);
  42. // }*/
  43. //
  44. // //向下调整建堆
  45. // //O(n)
  46. // for (int i = (n - 1 - 1) / 2; i >= 0; --i)
  47. // {
  48. // AdjustDown(a, n, i);
  49. // }
  50. //
  51. // int end = n - 1;
  52. // while (end > 0)
  53. // {
  54. // Swap(&a[0], &a[end]);
  55. // AdjustDown(a, end, 0);
  56. // --end;
  57. // }
  58. //}
  59. // 堆排序
  60. //int main()
  61. //{
  62. // int a[] = { 1,2,6,4,5,9,2,8 };
  63. // HeapSort(a, sizeof(a) / sizeof(int));
  64. //
  65. // for (int i = 0; i < sizeof(a) / sizeof(int); i++)
  66. // {
  67. // printf("%d ", a[i]);
  68. // }
  69. // printf("\n");
  70. //
  71. // return 0;
  72. //}
  73. //void CreateNDate()
  74. //{
  75. // //造数据
  76. // int n = 10000000;
  77. // srand(time(0));
  78. // const char* file = "data.txt";
  79. // FILE* fin = fopen(file, "w");
  80. // if (fin == NULL)
  81. // {
  82. // perror("fopen error");
  83. // return;
  84. // }
  85. // for (int i = 0; i < n; ++i)
  86. // {
  87. // int x = (rand() + i) % 10000000;
  88. // fprintf(fin, "%d\n", x);
  89. // }
  90. // fclose(fin);
  91. //}
  92. //
  93. //void PrintTopK(const char* file, int k)
  94. //{
  95. // FILE* fout = fopen(file, "r");
  96. // if (fout == NULL)
  97. // {
  98. // perror("fopen error");
  99. // return;
  100. // }
  101. // // 建一个k个数的小堆
  102. // int* minheap = (int*)malloc(sizeof(int) * k);
  103. // if (minheap == NULL)
  104. // {
  105. // perror("malloc fail");
  106. // return;
  107. // }
  108. // // 读取前k个,建小堆
  109. // for (int i = 0; i < k; i++)
  110. // {
  111. // fscanf(fout, "%d", &minheap[i]);
  112. // AdjustUp(minheap, i);
  113. // }
  114. //
  115. // int x = 0;
  116. // while (fscanf(fout, "%d", &x)!= EOF)
  117. // {
  118. // if (x > minheap[0])
  119. // {
  120. // minheap[0] = x;
  121. // AdjustDown(minheap, k, 0);
  122. // }
  123. // }
  124. //
  125. // for (int i = 0; i < k; i++)
  126. // {
  127. // printf("%d ", minheap[i]);
  128. // }
  129. // printf("\n");
  130. //
  131. // free(minheap);
  132. //
  133. // fclose(fout);
  134. //}
  135. //
  136. //int main()
  137. //{
  138. // //CreateNDate();
  139. // //PrintTopK("data.txt", 8);
  140. //
  141. // return 0;
  142. //}
  143. typedef int BTDataType;
  144. typedef struct BinaryTreeNode
  145. {
  146. BTDataType data;
  147. struct BinaryTreeNode* left;
  148. struct BinaryTreeNode* right;
  149. }TreeNode;
  150. TreeNode* BuyTreeNode(int x)
  151. {
  152. TreeNode* node = (TreeNode*)malloc(sizeof(TreeNode));
  153. assert(node);
  154. node->data = x;
  155. node->left = NULL;
  156. node->right = NULL;
  157. return node;
  158. }
  159. // 创建树
  160. TreeNode* CreateTree()
  161. {
  162. TreeNode* node1 = BuyTreeNode(1);
  163. TreeNode* node2 = BuyTreeNode(2);
  164. TreeNode* node3 = BuyTreeNode(3);
  165. TreeNode* node4 = BuyTreeNode(4);
  166. TreeNode* node5 = BuyTreeNode(5);
  167. TreeNode* node6 = BuyTreeNode(6);
  168. TreeNode* node7 = BuyTreeNode(7);
  169. node1->left = node2;
  170. node1->right = node4;
  171. node2->left = node3;
  172. node4->left = node5;
  173. node4->right = node6;
  174. node5->right = node7;
  175. return node1;
  176. }
  177. // 前序遍历
  178. void PrevOrder(TreeNode* root)
  179. {
  180. if (root == NULL)
  181. {
  182. printf("N ");
  183. return;
  184. }
  185. printf("%d ", root->data);
  186. PrevOrder(root->left);
  187. PrevOrder(root->right);
  188. }
  189. // 中序遍历
  190. void InOrder(TreeNode* root)
  191. {
  192. if (root == NULL)
  193. {
  194. printf("N ");
  195. return;
  196. }
  197. InOrder(root->left);
  198. printf("%d ", root->data);
  199. InOrder(root->right);
  200. }
  201. // 后序遍历
  202. void AfterOrder(TreeNode* root)
  203. {
  204. if (root == NULL)
  205. {
  206. printf("N ");
  207. return;
  208. }
  209. AfterOrder(root->left);
  210. AfterOrder(root->right);
  211. printf("%d ", root->data);
  212. }
  213. //二叉树的节点个数
  214. int TreeSize(TreeNode* root)
  215. {
  216. if (root == NULL)
  217. {
  218. return 0;
  219. }
  220. else
  221. {
  222. return 1 + TreeSize(root->left) + TreeSize(root->right);
  223. }
  224. }
  225. //二叉树叶子结点个数
  226. int TreeLeafSize(TreeNode* root)
  227. {
  228. //空返回0
  229. if (root == NULL)
  230. {
  231. return 0;
  232. }
  233. //不是空,是叶子,返回1
  234. if (root->left == NULL && root->right == NULL)
  235. {
  236. return 1;
  237. }
  238. //不是空也不是叶子 分治=左右叶子之和
  239. return TreeLeafSize(root->left) + TreeLeafSize(root->right);
  240. }
  241. // 二叉树的深度
  242. int TreeHeight(TreeNode* root)
  243. {
  244. if (root == NULL)
  245. {
  246. return 0;
  247. }
  248. else
  249. {
  250. return 1 + fmax(TreeHeight(root->left), TreeHeight(root->right));
  251. }
  252. }
  253. // 第K层节点个数
  254. int TreeLevelK(TreeNode* root, int k)
  255. {
  256. assert(k > 0);
  257. if (root == 0)
  258. {
  259. return 0;
  260. }
  261. if (k == 1)
  262. {
  263. return 1;
  264. }
  265. return TreeLevelK(root->left, k-1) + TreeLevelK(root->right, k-1);
  266. }
  267. //二叉树查找值为x的结点
  268. TreeNode* TreeFind(TreeNode* root, BTDataType x)
  269. {
  270. if (root == NULL)
  271. {
  272. return NULL;
  273. }
  274. if (root->data == x)
  275. {
  276. return root;
  277. }
  278. TreeNode* ret1 = TreeFind(root->left, x);
  279. if (ret1)
  280. {
  281. return ret1;
  282. }
  283. TreeNode* ret2 = TreeFind(root->right, x);
  284. if (ret2)
  285. {
  286. return ret2;
  287. }
  288. }
  289. // 通过前序遍历的数组“ABD##E#H##CF##G##”构建二叉树(代码还有可能有bug)
  290. TreeNode* TreeCreate(char* a, int* pi)
  291. {
  292. if (a[*pi] == '#')
  293. {
  294. (*pi)++;
  295. printf("%d", *pi);
  296. return NULL;
  297. }
  298. TreeNode* root = (TreeNode*)malloc(sizeof(TreeNode));
  299. if (root == NULL)
  300. {
  301. perror("malloc fail");
  302. exit(-1);
  303. }
  304. root->data = a[(*pi)++];
  305. root->left = TreeCreate(a, pi);
  306. root->right = TreeCreate(a, pi);
  307. return root;
  308. }
  309. void DestroyTree(TreeNode* root)
  310. {
  311. if (root == NULL)
  312. {
  313. return;
  314. }
  315. DestroyTree(root->left);
  316. DestroyTree(root->right);
  317. free(root);
  318. }
  319. // 层序遍历代码在最后,要在main函数之前先进行声明
  320. void LevelOrder(TreeNode* root);
  321. // 输出每一层的声明
  322. void EveryLevelOrder(TreeNode* root);
  323. //判断二又树是否是完全二又树的声明
  324. int TreeComplete(TreeNode* root);
  325. int main()
  326. {
  327. TreeNode* root = CreateTree();
  328. // 前序遍历
  329. PrevOrder(root);
  330. printf("\n");
  331. // 中序遍历
  332. InOrder(root);
  333. printf("\n");
  334. // 后序遍历
  335. AfterOrder(root);
  336. printf("\n");
  337. LevelOrder(root);
  338. EveryLevelOrder(root);
  339. printf("TreeSize:%d\n", TreeSize(root));
  340. printf("TreeLeafSize:%d\n", TreeLeafSize(root));
  341. printf("TreeHeight:%d\n", TreeHeight(root));
  342. printf("TreeLevelK:%d\n", TreeLevelK(root,3));
  343. printf("TreeFind:%p\n", TreeFind(root,3));
  344. TreeNode* ret = TreeFind(root, 5);
  345. printf("TreeFind:%p\n", ret);
  346. /*ret->data++;*/
  347. printf("TreeComplete:%d\n", TreeComplete(root));// 当前树不是完全二叉树,把node2指向node7就成了完全二叉树了
  348. // node5->right = node7;变为node2->right = node7;
  349. DestroyTree(root);
  350. root = NULL;
  351. }
  352. // 层序遍历用到的队列
  353. void QueueInit(Queue* pq)
  354. {
  355. assert(pq);
  356. pq->phead = pq->ptail = NULL;
  357. pq->size = 0;
  358. }
  359. void QueueDestroy(Queue* pq)
  360. {
  361. assert(pq);
  362. QNode* cur = pq->phead;
  363. while (cur)
  364. {
  365. QNode* next = cur->next;
  366. free(cur);
  367. cur = next;
  368. }
  369. pq->phead = pq->ptail = NULL;
  370. pq->size = 0;
  371. }
  372. void QueuePush(Queue* pq, QDataType x)
  373. {
  374. assert(pq);
  375. QNode* newnode = (QNode*)malloc(sizeof(QNode));
  376. if (newnode == NULL)
  377. {
  378. perror("malloc fail");
  379. return;
  380. }
  381. newnode->val = x;
  382. newnode->next = NULL;
  383. if (pq->ptail == NULL)
  384. {
  385. pq->ptail = pq->phead = newnode;
  386. }
  387. else
  388. {
  389. pq->ptail->next = newnode;
  390. pq->ptail = newnode;
  391. }
  392. pq->size++;
  393. }
  394. void QueuePop(Queue* pq)
  395. {
  396. assert(pq);
  397. // 空节点
  398. assert(pq->phead);
  399. QNode* del = pq->phead;
  400. pq->phead = pq->phead->next;
  401. free(del);
  402. // 一个节点的时候,phead向前走
  403. // del被free,ptail此时和del指的是一个节点,如果free,就变成了野指针
  404. if (pq->phead == NULL)
  405. {
  406. pq->ptail = NULL;
  407. }
  408. pq->size--;
  409. }
  410. QDataType QueueFront(Queue* pq)
  411. {
  412. assert(pq);
  413. // 空节点
  414. assert(pq->phead);
  415. return pq->phead->val;
  416. }
  417. QDataType QueueBack(Queue* pq)
  418. {
  419. assert(pq);
  420. // 空节点
  421. assert(pq->phead);
  422. return pq->ptail->val;
  423. }
  424. bool QueueEmpty(Queue* pq)
  425. {
  426. assert(pq);
  427. return pq->phead == NULL;
  428. }
  429. int QueueSize(Queue* pq)
  430. {
  431. assert(pq);
  432. return pq->size;
  433. }
  434. // 层序遍历
  435. void LevelOrder(TreeNode* root)
  436. {
  437. Queue q;
  438. QueueInit(&q);
  439. if (root)
  440. QueuePush(&q, root);
  441. while (!QueueEmpty(&q))
  442. {
  443. TreeNode* front = QueueFront(&q);
  444. QueuePop(&q);
  445. printf("%d ", front->data);
  446. if (front->left)
  447. QueuePush(&q, front->left);
  448. if (front->right)
  449. QueuePush(&q, front->right);
  450. }
  451. printf("\n");
  452. QueueDestroy(&q);
  453. }
  454. // 每一行跟一个换行
  455. void EveryLevelOrder(TreeNode* root)
  456. {
  457. Queue q;
  458. QueueInit(&q);
  459. if (root)
  460. QueuePush(&q, root);
  461. int levelSize = 1;// 当前层的个数
  462. while (!QueueEmpty(&q))
  463. {
  464. while (levelSize--) // 减到0表示这一层出完了,也就是下一层都带入了,当前队列里都是下一层的数
  465. {
  466. TreeNode* front = QueueFront(&q);
  467. QueuePop(&q);
  468. printf("%d ", front->data);
  469. if (front->left)
  470. QueuePush(&q, front->left);
  471. if (front->right)
  472. QueuePush(&q, front->right);
  473. }
  474. printf("\n");
  475. levelSize = QueueSize(&q); //记录下一层的个数,也就是当前队列里的个数
  476. }
  477. printf("\n");
  478. QueueDestroy(&q);
  479. }
  480. //判断二又树是否是完全二又树
  481. int TreeComplete(TreeNode* root)
  482. {
  483. Queue q;
  484. QueueInit(&q);
  485. if (root)
  486. QueuePush(&q, root);
  487. int levelSize = 1;// 当前层的个数
  488. while (!QueueEmpty(&q))
  489. {
  490. TreeNode* front = QueueFront(&q);
  491. QueuePop(&q);
  492. if (front == NULL)
  493. break;
  494. QueuePush(&q, front->left);
  495. QueuePush(&q, front->right);
  496. }
  497. // 层序遍历的原理入队列,前边遇到空以后,后面还有非空就不是完全二叉树
  498. while (!QueueEmpty(&q))
  499. {
  500. TreeNode* front = QueueFront(&q);
  501. QueuePop(&q);
  502. if (front)
  503. {
  504. return false;
  505. }
  506. }
  507. QueueDestroy(&q);
  508. return true;
  509. }

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

闽ICP备14008679号