当前位置:   article > 正文

数据结构_第十一关:二叉树的链式结构_第11关:树的计数

第11关:树的计数

目录

1.二叉树链式结构的实现

1.1前置说明

1.2二叉树的遍历

1.3二叉树遍历的实现:

1)先序遍历、中序遍历、后续遍历代码如下

2)层序遍历:

1.4结点个数以及高度的计算

1)求二叉树的总节点:

2)求叶子节点的个数

3)求树的深度/高度

4)求第K层的结点数 k>=1

5)二叉树查找值未x的节点 

2.二叉树的基础OJ题练习


1.二叉树链式结构的实现

1.1前置说明

此次二叉树链式结构的讲解先不进行增删查改,之后学完c++再进一步学习

事实上,二叉树的增删查改没有价值,
学习二叉树的意义是:再其基础上完成对搜索二叉树的学习

搜索二叉树:左孩子比父节点小,右孩子比父节点大

搜索二叉树学习完之后,就到了对平衡二叉树(AVL树+红黑树)的学习,
这里就不多介绍了(绝不是因为我现在也不太懂^.^)

1.2二叉树的遍历

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

四种遍历方法:

  • 先序遍历:根、左子树、右子树
  • 中序遍历:左子树、跟、右子树
  • 后序遍历:左子树、右子树、跟
  • 层序遍历:从第一层开始、每层从左到右,一层一层的走

前序遍历结果:1 2 3 4 5 6

中序遍历结果:3 2 1 5 4 6

后序遍历结果:3 2 5 6 4 1

层次遍历结果:1 2 4 3 5 6

练习:请写出下面的前序/中序/后序/层序遍历

 选择题:

1.某完全二叉树按层次输出(同一层从左到右)的序列为 ABCDEFGH 。

该完全二叉树的前序序列为( )
A ABDHECFG
B ABCDEFGH
C HDBEAFCG
D HDEBFGCA


2.二叉树的先序遍历和中序遍历如下:先序遍历:EFHIGJK;中序遍历:HFIEJKG.

则二叉树根结点为()
A E
B F
C G
D H


3.设一课二叉树的中序遍历序列:badce,后序遍历序列:bdeca,则二叉树前序遍历序列

为(  )
A adbce
B decab
C debac
D abcde


4.某二叉树的后序遍历序列与中序遍历序列相同,均为 ABCDEF ,则按层次输出

(同一层从左到右)的序列为
A FEDCBA 
B CBAFED
C DEFCBA
D ABCDEF

答案:1.A         2.A        3.D        4.A

1.3二叉树遍历的实现:

在实现前,我们先要建立一个树,因为我们暂时不学习二叉树的建立,

所以我们直接手动建立如下图的二叉树

手动建立如下:

  1. #include<stdio.h>
  2. #include<stdlib.h>
  3. typedef int BTDataType;
  4. typedef struct BinaryTreeNode
  5. {
  6. BTDataType data;
  7. struct BinaryTreeNode* left;
  8. struct BinaryTreeNode* right;
  9. }BTNode;
  10. int main()
  11. {
  12. BTNode* root;
  13. BTNode* n1 = BuyBTNode(1);
  14. BTNode* n2 = BuyBTNode(2);
  15. BTNode* n3 = BuyBTNode(3);
  16. BTNode* n4 = BuyBTNode(4);
  17. BTNode* n5 = BuyBTNode(5);
  18. BTNode* n6 = BuyBTNode(6);
  19. n1->left = n2;
  20. n1->right = n4;
  21. n2->left = n3;
  22. n4->left = n5;
  23. n4->right = n6;
  24. return 0
  25. }

1)先序遍历、中序遍历、后续遍历代码如下

因为他们的代码只是遍历顺序不同,所以就放一起了

  1. //前序遍历
  2. void PrevOrder(BTNode* root)
  3. {
  4. if (root == NULL)
  5. {
  6. //printf("NULL ");
  7. return;
  8. }
  9. printf("%d ", root->data);
  10. PrevOrder(root->left);
  11. PrevOrder(root->right);
  12. }
  13. //中序遍历
  14. void InOrder(BTNode* root)
  15. {
  16. if (root == NULL)
  17. {
  18. //printf("NULL ");
  19. return;
  20. }
  21. PrevOrder(root->left);
  22. printf("%d ", root->data);
  23. PrevOrder(root->right);
  24. }
  25. //后续遍历
  26. void PostOrder(BTNode* root)
  27. {
  28. if (root == NULL)
  29. {
  30. //printf("NULL ");
  31. return;
  32. }
  33. PrevOrder(root->left);
  34. PrevOrder(root->right);
  35. printf("%d ", root->data);
  36. }

2)层序遍历:

  1. 首先,将二叉树的根节点放入一个队列中

  2. 从队列的头部取出一个元素(记为当前元素cur),将cur的左孩子作为新节点放入队列尾部,再将cur的右孩子作为新节点放入队列尾部。因为队列是先进先出的,所以这样处理后,下一次取出来的就是左孩子,再下一次取出来的就是右孩子了。

  3. 重复步骤2,直到队列为空为止。

  1. void LevelOrder(BTNode* root)
  2. {
  3. if (root == NULL)
  4. return;
  5. BTNode* queue[1000]; // 定义队列,最多存放1000个节点
  6. int head = 0, tail = 0;
  7. queue[tail++] = root;
  8. while (head < tail)
  9. {
  10. BTNode* curNode = queue[head++]; // 出队
  11. printf("%d ", curNode->data);
  12. if (curNode->left != NULL)
  13. queue[tail++] = curNode->left; // 左孩子入队
  14. if (curNode->right != NULL)
  15. queue[tail++] = curNode->right; // 右孩子入队
  16. }
  17. }

1.4结点个数以及高度的计算

因为二叉树适合用递归的方式来计算,所以不论是上面的遍历二叉树还是其他计算,他们的代码都是用递归来实现的

1)求二叉树的总节点:

有两种方法:

  1. 定义一个全局变量size,在每次计算前都要手动将其置为0
  2. 直接用递归来进行计算

方法1:

  1. int size = 0;//定义全局变量
  2. void TreeSize1(BTNode* root)
  3. {
  4. if (root == NULL)
  5. return;
  6. size++;
  7. TreeSize1(root->left);
  8. TreeSize1(root->right);
  9. }
  10. //使用时:
  11. int main()
  12. {
  13. size = 0; //size是全局变量,每次使用前都需要手动置0,否则会在之前的基础上再加
  14. TreeSize1(n1);
  15. printf("TreeSize1:%d\n", size);
  16. TreeSize1(n1);
  17. printf("TreeSize1(size未置0):%d\n", size);
  18. size = 0;
  19. TreeSize1(n1);
  20. printf("TreeSize1(重新将size置0):%d\n", size);
  21. return 0;
  22. }

结果如下: 

 方法二:直接用递归来求:

  1. int TreeSize2(BTNode* root)
  2. {
  3. return root == NULL ? 0 : TreeSize2(root->left) + TreeSize2(root->right) + 1;
  4. }
  5. //使用
  6. int main()
  7. {
  8. printf("TreeSize2:%d\n", TreeSize2(n1));
  9. printf("TreeSize2:%d\n", TreeSize2(n1));
  10. printf("TreeSize2:%d\n", TreeSize2(n1));
  11. return 0;
  12. }

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)求树的深度/高度

  1. int TreeHeight(BTNode* root)
  2. {
  3. if (root == NULL)
  4. {
  5. return 0;
  6. }
  7. //保留算出的数据,防止重复计算比较
  8. int leftHeight = TreeHeight(root->left);
  9. int rightHeight = TreeHeight(root->right);
  10. return leftHeight > rightHeight ? leftHeight + 1 : rightHeight + 1;
  11. }

注意这里写的时候不要像下面那样直接返回,

return   TreeLeafSize(root->left) > TreeLeafSize(root->right) ? 
            TreeLeafSize(root->left) + 1 : TreeLeafSize(root->right) + 1;

这种写法十分浪费资源,会有很多重复的计算,导致效率特别低

正确的写法是先将其保存起来,再进行比较和返回递归

4)求第K层的结点数 k>=1

  1. int TreeKLevelSize(BTNode* root, int k)
  2. {
  3. if (root == NULL)
  4. return 0;
  5. if (k == 1)
  6. return 1;
  7. // k > 1 子树的k-1
  8. return TreeKLevelSize(root->left, k - 1)+ TreeKLevelSize(root->right, k - 1);
  9. }

5)二叉树查找值未x的节点 

  1. BTNode* TreeFind(BTNode* root, BTDataType x)
  2. {
  3. if (root == NULL)
  4. return NULL;
  5. if (root->data == x)
  6. return root;
  7. BTNode* ret1 = TreeFind(root->left, x);
  8. if (ret1)
  9. return ret1;
  10. BTNode* ret2 = TreeFind(root->right, x);
  11. if (ret2)
  12. return ret2;
  13. }

2.二叉树的基础OJ题练习

(思路和代码下一关里面讲)

  • 1. 单值二叉树。                        OJ题链接
  • 2. 检查两颗树是否相同             OJ题链接
  • 3. 对称二叉树。                        OJ题链接
  • 4. 另一颗树的子树。                 OJ题链接
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/黑客灵魂/article/detail/948462
推荐阅读
相关标签
  

闽ICP备14008679号