• 【数据结构】二叉树--链式结构的实现 (遍历)


    目录

    一 二叉树的遍历

    1 构建一个二叉树

    2 前序遍历

    3 中序遍历

    4 后续遍历

    5 层序 

    6 二叉树销毁

    二 应用(递归思想)

    1 二叉树节点个数

    2 叶子节点个数

    3 第K层的节点个数

    4 二叉树查找值为x的节点

    5 判断是否是二叉树


    一 二叉树的遍历

    学习二叉树结构,最简单的方式就是遍历。所谓二叉树遍历(Traversal)是按照某种特定的规则,依次对二叉 树中的节点进行相应的操作,并且每个节点只操作一次。访问结点所做的操作依赖于具体的应用问题。 遍历 是二叉树上最重要的运算之一,也是二叉树上进行其它运算的基础

    二叉树是: 1. 空树  2. 非空:根节点,根节点的左子树、根节点的右子树组成的。

    前序、中序以及后序遍历: 

    按照规则,二叉树的遍历有:前序/中序/后序的递归结构遍历:

    1. 前序遍历(Preorder Traversal 亦称先序遍历)——访问根结点的操作发生在遍历其左右子树之前。

    2. 中序遍历(Inorder Traversal)——访问根结点的操作发生在遍历其左右子树之中(间)。

    3. 后序遍历(Postorder Traversal)——访问根结点的操作发生在遍历其左右子树之后。

    由于被访问的结点必是某子树的根,所以N(Node)、L(Left subtree)和R(Right subtree)又可解释为 根、根的左子树和根的右子树。NLR、LNR和LRN分别又称为先根遍历、中根遍历和后根遍历。

    代码实现:

    1 构建一个二叉树

    1. typedef struct BinaryTreeNode
    2. {
    3. struct BinaryTreeNode* left;
    4. struct BinaryTreeNode* right;
    5. int val;
    6. }BTNode;
    7. BTNode* BuyNode(int x)
    8. {
    9. BTNode* node = (BTNode*)malloc(sizeof(BTNode));
    10. if (node == NULL)
    11. {
    12. perror("malloc fail");
    13. exit(-1);
    14. }
    15. node->left = NULL;
    16. node->right = NULL;
    17. node->val = x;
    18. return node;
    19. }
    20. int main()
    21. {
    22. BTNode* node1 = BuyNode(1);
    23. BTNode* node2 = BuyNode(2);
    24. BTNode* node3 = BuyNode(3);
    25. BTNode* node4 = BuyNode(4);
    26. BTNode* node5 = BuyNode(5);
    27. BTNode* node6 = BuyNode(6);
    28. node1->left = node2;
    29. node1->right = node4;
    30. node2->left = node3;
    31. node4->left = node5;
    32. node4->right = node6;
    33. PrevOrder(node1);
    34. printf("\n");
    35. InOrder(node1);
    36. printf("\n");
    37. PostOrder(node1);
    38. printf("\n");
    39. return 0;
    40. }

     2 前序遍历

    1. //前序遍历
    2. void PrevOrder(BTNode* root)
    3. {
    4. if (root == NULL)
    5. {
    6. printf("NULL ");
    7. return;
    8. }
    9. printf("%d ", root->val);
    10. PrevOrder(root->left);
    11. PrevOrder(root->right);
    12. }

    3 中序遍历

    1. //中序遍历
    2. void InOrder(BTNode* root)
    3. {
    4. if (root == NULL)
    5. {
    6. printf("NULL ");
    7. return;
    8. }
    9. InOrder(root->left);
    10. printf("%d ", root->val);
    11. InOrder(root->right);
    12. }

     4 后续遍历

    1. //后序遍历
    2. void PostOrder(BTNode* root)
    3. {
    4. if (root == NULL)
    5. {
    6. printf("NULL ");
    7. return;
    8. }
    9. PostOrder(root->left);
    10. PostOrder(root->right);
    11. printf("%d ", root->val);
    12. }

    5 层序 

    1. void QueueInit(Que* pq)
    2. {
    3. assert(pq);
    4. pq->head = pq->tail = NULL;
    5. pq->size = 0;
    6. }
    7. void QueuePush(Que* pq, QDataType x)
    8. {
    9. assert(pq);
    10. QNode* newnode = (QNode*)malloc(sizeof(QNode));
    11. if (newnode == NULL)
    12. {
    13. perror("malloc fail");
    14. exit(-1);
    15. }
    16. newnode->next = NULL;
    17. newnode->val = x;
    18. if (pq->tail == NULL)
    19. {
    20. pq->head = pq->tail = newnode;
    21. }
    22. else
    23. {
    24. pq->tail->next = newnode;
    25. pq->tail = newnode;
    26. }
    27. pq->size++;
    28. }
    29. bool QueueEmpty(Que* pq)
    30. {
    31. assert(pq);
    32. return pq->head == NULL;
    33. }
    34. void QueuePop(Que* pq)
    35. {
    36. assert(pq);
    37. assert(!QueueEmpty(pq));
    38. if (pq->head->next == NULL)
    39. {
    40. free(pq->head);
    41. pq->head = pq->tail = NULL;
    42. }
    43. else
    44. {
    45. QNode* next = pq->head->next;
    46. free(pq->head);
    47. pq->head = next;
    48. }
    49. pq->size--;
    50. }
    51. QDataType QueueFront(Que* pq)
    52. {
    53. assert(pq);
    54. assert(!QueueEmpty(pq));
    55. return pq->head->val;
    56. }
    57. void LevelOrder(BTNode* root)
    58. {
    59. Que q;
    60. QueueInit(&q);
    61. if (root)
    62. {
    63. QueuePush(&q, root);
    64. }
    65. while (!QueueEmpty(&q))
    66. {
    67. BTNode* front = QueueFront(&q);
    68. printf("%d ", front->val);
    69. if (front->left)
    70. {
    71. QueuePush(&q, front->left);
    72. }
    73. if (front->right)
    74. {
    75. QueuePush(&q, front->right);
    76. }
    77. QueuePop(&q);
    78. }
    79. }

    6 二叉树销毁

    1. //二叉树的销毁
    2. void TreeDestroy(BTNode* root)
    3. {
    4. if (root == NULL)
    5. {
    6. return;
    7. }
    8. TreeDestroy(root->left);
    9. TreeDestroy(root->right);
    10. free(root);
    11. }

    二 应用(递归思想)

    1 二叉树节点个数

    1. int size = 0;
    2. int TreeSize(BTNode* root)
    3. {
    4. if (root == NULL)
    5. {
    6. return 0;
    7. }
    8. else
    9. {
    10. size++;
    11. }
    12. TreeSize(root->left);
    13. TreeSize(root->right);
    14. return size;
    15. }

    我们还可以改进

    1. int TreeSize(BTNode* root)
    2. {
    3. return root == NULL ? 0 : TreeSize(root->left) + TreeSize(root->right) + 1;
    4. }

     2 叶子节点个数

    1. int TreeLeafSize(BTNode* root)
    2. {
    3. if (root == NULL)
    4. {
    5. return 0;
    6. }
    7. if (root->left == NULL && root->right == NULL)
    8. {
    9. return 1;
    10. }
    11. return TreeLeafSize(root->left) + TreeLeafSize(root->right);
    12. }

    3 第K层的节点个数

    1. int TreeKLevel(BTNode* root, int k)
    2. {
    3. assert(k > 0);
    4. if (root == NULL)
    5. {
    6. return 0;
    7. }
    8. if (k == 1)
    9. {
    10. return 1;
    11. }
    12. return TreeKLevel(root->left, k-1) + TreeKLevel(root->right, k-1);
    13. }

     4 二叉树查找值为x的节点

    1. BTNode* TreeFind(BTNode* root, int x)
    2. {
    3. if (root == NULL)
    4. {
    5. return NULL;
    6. }
    7. if (root->val == x)
    8. {
    9. return root;
    10. }
    11. BTNode* ret = NULL;
    12. //从左树找 找到了就返回 不找右树了
    13. ret = TreeFind(root->left, x);
    14. if (ret)
    15. {
    16. return ret;
    17. }
    18. //左树没找到 就开始找右树
    19. ret = TreeFind(root->right, x);
    20. if (ret)
    21. {
    22. return ret;
    23. }
    24. }

    5 判断是否是二叉树

    1. void QueueInit(Que* pq)
    2. {
    3. assert(pq);
    4. pq->head = pq->tail = NULL;
    5. pq->size = 0;
    6. }
    7. void QueueDestroy(Que* pq)
    8. {
    9. assert(pq);
    10. QNode* cur = pq->head;
    11. while (cur)
    12. {
    13. QNode* next = cur->next;
    14. free(cur);
    15. cur = next;
    16. }
    17. pq->head = pq->tail = NULL;
    18. pq->size = 0;
    19. }
    20. void QueuePush(Que* pq, QDataType x)
    21. {
    22. assert(pq);
    23. QNode* newnode = (QNode*)malloc(sizeof(QNode));
    24. if (newnode == NULL)
    25. {
    26. perror("malloc fail");
    27. exit(-1);
    28. }
    29. newnode->next = NULL;
    30. newnode->val = x;
    31. if (pq->tail == NULL)
    32. {
    33. pq->head = pq->tail = newnode;
    34. }
    35. else
    36. {
    37. pq->tail->next = newnode;
    38. pq->tail = newnode;
    39. }
    40. pq->size++;
    41. }
    42. bool QueueEmpty(Que* pq)
    43. {
    44. assert(pq);
    45. return pq->head == NULL;
    46. }
    47. void QueuePop(Que* pq)
    48. {
    49. assert(pq);
    50. assert(!QueueEmpty(pq));
    51. if (pq->head->next == NULL)
    52. {
    53. free(pq->head);
    54. pq->head = pq->tail = NULL;
    55. }
    56. else
    57. {
    58. QNode* next = pq->head->next;
    59. free(pq->head);
    60. pq->head = next;
    61. }
    62. pq->size--;
    63. }
    64. QDataType QueueFront(Que* pq)
    65. {
    66. assert(pq);
    67. assert(!QueueEmpty(pq));
    68. return pq->head->val;
    69. }
    70. int TreeComplete(BTNode* root)
    71. {
    72. Que q;
    73. QueInit(&q);
    74. if (root != NULL)
    75. {
    76. QueuePush(&q, root);
    77. }
    78. //找空节点
    79. while (!QueueEmpty(&q))
    80. {
    81. BTNode* front = QueueFront(&q);
    82. if (front == NULL)
    83. {
    84. break;
    85. }
    86. QueuePush(&q, front->left);
    87. QueuePush(&q, front->right);
    88. QueuePop(&q);
    89. }
    90. //已经找到空节点
    91. while (!QueueEmpty(&q))
    92. {
    93. BTNode* front = QueueFront(&q);
    94. QueuePop(&q);
    95. if (front != NULL)
    96. {
    97. QueueDestroy(&q);
    98. return false;
    99. }
    100. }
    101. QueueDestroy(&q);
    102. return true;
    103. }

    二叉树的链式结构的本质思想是递归, 对于递归不了解的小伙伴可以看看我之前的博客, 也可以自己尝试画一下递归展开图,下一节讲OJ题目.实战才最有效!继续加油! 

  • 相关阅读:
    golang学习笔记01——基本数据类型
    【第54篇】一种用于视觉识别的快速知识蒸馏框架
    docker部署mysql主从备份
    猫罐头怎么选择?市面上最受欢迎的5款猫罐头推荐!
    33.JavaScript映射与集合(Map、Set)数据类型基础知识介绍与使用
    JUC_锁是什么,Synchronized与Lock的区别
    生成树协议:监控 STP 端口和交换机
    apache html调用bash脚本案例
    Elasticsearch REST API 初探:索引与搜索文档的奥秘
    C logistics
  • 原文地址:https://blog.csdn.net/yf214wxy/article/details/133716161