当前位置:   article > 正文

【数据结构】二叉树经典OJ练习_二叉树练习题oj

二叉树练习题oj

目录

前言

1.单值二叉树

2.相同的树

3.对称二叉树

4.二叉树的前序遍历

5.另一棵树的子树

6.平衡二叉树 

7.二叉树遍历


前言

本章只是二叉树的部分简单练习,对于这部分题目大多比较简单,但重要的不是能过OJ,而是深入理解每一道题的解题原理。

多思考,勤动手,才是正解。对于编程,我们要做到画图半小时,写代码五分钟;而不是写代码五分钟,调试三十分钟。

理解递归思想,分治思想,温故而知新~

1.单值二叉树

单值二叉树

根据题目描述,判断二叉树的每个节点的值是否相同。

方法:

  1. 先判断根节点与左右子节点的值是否相等。
  2. 进而递归判断左右子树的根节点与左右子节点的值是否相等。

代码如下: 

  1. bool isUnivalTree(struct TreeNode* root){
  2. 1.空树也是单值,返回真
  3. if(root == NULL)
  4. {
  5. return true;
  6. }
  7. 2.判断根节点与左子节点,前提是左子树不为空,为空不需比较
  8. if(root->left&&root->val != root->left->val)
  9. {
  10. return false;
  11. }
  12. 3.判断根节点与右子节点
  13. if(root->right&&root->val != root->right->val)
  14. {
  15. return false;
  16. }
  17. //递归继续判断左右子树
  18. return isUnivalTree(root->left)&&isUnivalTree(root->right);
  19. }

2.相同的树

相同的树

这道题比较简单,先比较根节点的值,然后递归比较左右子树的节点是否相同即可。

直接上代码吧:

  1. bool isSameTree(struct TreeNode* p, struct TreeNode* q){
  2. //1.两树都为空返回真
  3. if(p == NULL && q == NULL)
  4. {
  5. return true;
  6. }
  7. //2.两树不相同有两种情况
  8. //(1)两树节点的值不相等
  9. //(2)两树一个节点为空,一个不为空
  10. if((p == NULL || q == NULL) || (p->val != q->val ))
  11. {
  12. return false;
  13. }
  14. //若当前节点相等,则递归比较两树左右子树
  15. return isSameTree(p->left, q->left) && isSameTree(p->right, q->right);
  16. }

3.对称二叉树

对称二叉树

这道题相当于是上一题的变形版,对称即头节点的左右子树完全相同。

方法:

  1. 将头节点左右子树看成两颗独立的树
  2. 然后将左树的左节点与右树的右节点比较,将左树的右节点与右树的左节点比较。

 代码如下:

  1. //子函数,比较两树是否相同
  2. bool _isSymmetric(struct TreeNode*left, struct TreeNode*right)
  3. {
  4. if(left == NULL && right == NULL)
  5. {
  6. return true;
  7. }
  8. if((left == NULL || right == NULL) || (left->val != right->val))
  9. {
  10. return false;
  11. }
  12. return _isSymmetric(left->left,right->right)&&_isSymmetric(left->right,right->left);
  13. }
  14. bool isSymmetric(struct TreeNode* root){
  15. //1.空树也是对称二叉树,返回真
  16. if(root == NULL)
  17. {
  18. return 0;
  19. }
  20. //2.因为我们需要比较两树是否相同,需传两个参数,这里需要创建子函数
  21. return _isSymmetric(root->left,root->right);
  22. }

4.二叉树的前序遍历

二叉树的前序遍历

二叉树的中序遍历

二叉树的后序遍历

这里二叉树的前中后序遍历类似,所以只做前序遍历。

与二叉树链式结构中实现的前序遍历不同的是,这里需要将每个节点的值存入数组中。

方法:

  1. 先找到需要创建数组的大小。
  2. 根据前序遍历将每个节点的数据存入数组。 

代码如下:

  1. //因为不知道需malloc数组的大小,先创建求二叉树节点个数的函数(前面介绍过,这里就不再讲)
  2. int TreeSize(struct TreeNode* root)
  3. {
  4. if(root==NULL)
  5. {
  6. return 0;
  7. }
  8. return TreeSize(root->left)+TreeSize(root->right)+1;
  9. }
  10. //前序遍历子函数
  11. void PrevOrder(struct TreeNode* root,int*arr,int*pi)
  12. {
  13. if(root==NULL)
  14. {
  15. return;
  16. }
  17. arr[(*pi)++] = root->val;//将节点数据放入数组
  18. //因为将数据放入数组后,下标位置会向后移动,
  19. //需改变i的值,所以要传i的地址
  20. PrevOrder(root->left,arr,pi);
  21. PrevOrder(root->right,arr,pi);
  22. }
  23. //前序遍历
  24. int* preorderTraversal(struct TreeNode* root, int* returnSize){
  25. //1.求节点个数
  26. int size = TreeSize(root);
  27. //创建数组
  28. int*arr = (int*)malloc(sizeof(int)*size);
  29. //输出型参数
  30. *returnSize = size;
  31. int i =0;
  32. //同样,因为参数限制,递归时不能使用本函数,所以需要创建子函数实现
  33. PrevOrder(root,arr,&i);
  34. return arr;
  35. }

5.另一棵树的子树

另一颗子树

这道题也相当于是判断两颗树是否相同的变形题。

方法:

  1. 先判断两颗树是否相同。
  2. 然后判断左右子树是否是与另一颗树相同。

代码如下:

  1. //子函数:判断两棵树是否相同
  2. bool _isSubtree(struct TreeNode*a, struct TreeNode*b)
  3. {
  4. if(a==NULL&&b==NULL)
  5. {
  6. return true;
  7. }
  8. if((a==NULL||b==NULL)||a->val!=b->val)
  9. {
  10. return false;
  11. }
  12. return _isSubtree(a->left,b->left)&&_isSubtree(a->right,b->right);
  13. }
  14. bool isSubtree(struct TreeNode* root, struct TreeNode* subRoot){
  15. //1.root为空则肯定不是子树,返回false
  16. if(root == NULL)
  17. {
  18. return false;
  19. }
  20. //2.判断两颗树是否相同
  21. if(_isSubtree(root,subRoot))
  22. {
  23. return true;
  24. }
  25. //3.判断左右子树与另一颗是否相同,只需要一颗相同即可
  26. return isSubtree(root->left,subRoot)||isSubtree(root->right,subRoot);
  27. }

6.平衡二叉树 

平衡二叉树

这道题是二叉树链式结构中求二叉树深度的变形。

方法:

利用分治思想:

先求根节点的左右子树的深度之差的绝对值是否大于1。

再求左右子节点的子树深度之差。

  1. //求二叉树深度
  2. int TreeDepth(struct TreeNode* root)
  3. {
  4. if(root == NULL)
  5. {
  6. return 0;
  7. }
  8. int leftdepth = TreeDepth(root->left);
  9. int rightdepth = TreeDepth(root->right);
  10. return leftdepth>rightdepth?leftdepth+1:rightdepth+1;
  11. }
  12. bool isBalanced(struct TreeNode* root){
  13. if(root==NULL)
  14. {
  15. return true;
  16. }
  17. //左子树深度
  18. int l = TreeDepth(root->left);
  19. //右子树深度
  20. int r = TreeDepth(root->right);
  21. //判断是否是平衡二叉树
  22. int x = l-r;
  23. if(x < 0)
  24. {
  25. x = r-l;
  26. }
  27. if(x>1)
  28. {
  29. return false;
  30. }
  31. //继续判断左右子树的子树
  32. return isBalanced(root->left)&&isBalanced(root->right);
  33. }

7.二叉树遍历

二叉树遍历

这道题设计的是IO型,所以需要我们自己写结构体和main函数,需自己调用函数实现。

方法:

  1. 创建函数创建二叉树节点。
  2. 创建函数前序遍历二叉树。

代码如下:

  1. #include<stdio.h>
  2. #include<stdlib.h>
  3. //二叉树节点结构体
  4. struct BTNode
  5. {
  6. char val;
  7. struct BTNode*left;
  8. struct BTNode*right
  9. };
  10. //创建节点,以及按照数组的每个值创建二叉树
  11. struct BTNode* CreatNode(char* str,int*pi)
  12. {
  13. //当字符为'#'时表示该节点为空
  14. if(str[*pi]=='#')
  15. {
  16. (*pi)++;
  17. return NULL;
  18. }
  19. //创建节点
  20. struct BTNode*root = (struct BTNode*)malloc(sizeof(struct BTNode));
  21. //将字符串字符放入节点
  22. root->val = str[(*pi)++];
  23. //递归创建左右节点
  24. root->left = CreatNode(str,pi);
  25. root->right = CreatNode(str,pi);
  26. return root;
  27. }
  28. //前序遍历输出节点
  29. void Inorder(struct BTNode*root)
  30. {
  31. if(root==NULL)
  32. {
  33. return;
  34. }
  35. Inorder(root->left);
  36. //输出节点
  37. printf("%c ",root->val);
  38. Inorder(root->right);
  39. }
  40. int main()
  41. {
  42. char str[100] = {0};
  43. int i = 0;
  44. while(scanf("%s",str)!=EOF)
  45. {
  46. struct BTNode*root = CreatNode(str,&i);
  47. Inorder(root);
  48. }
  49. return 0;
  50. }

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

闽ICP备14008679号