当前位置:   article > 正文

数据结构_第十二关:二叉树的基础OJ题练习

数据结构_第十二关:二叉树的基础OJ题练习

目录

1.单值二叉树

2.相同的树

3.另一棵树的子树

4.反转二叉树

5.对称二叉树

6.二叉树的结构及遍历

扩展:如何判断是不是完全二叉树、二叉树的销毁

1)判断是不是完全二叉树

2)二叉树的销毁


1.单值二叉树

OJ题链接https://leetcode.cn/problems/univalued-binary-tree/

 思路:

  • 先判断左子树,左子树不为空的情况下,左子树的值不等于根的值,返回false
  • 在判断右子树,左子树不为空的情况下,左子树的值不等于根的值,返回false
  • 最后如果以上两个条件都不满足,说明左右孩子的值和根的值相同,进行递归调用
    返回该函数的左子树与上右子树

代码:

  1. bool isUnivalTree(struct TreeNode* root)
  2. {
  3. if(root==NULL)
  4. return true;
  5. if(root->left && root->left->val != root->val)
  6. return false;
  7. if(root->right && root->right->val != root->val)
  8. return false;
  9. return isUnivalTree(root->left) && isUnivalTree(root->right);
  10. }

2.相同的树

OJ题链接https://leetcode.cn/problems/same-tree/

思路:

  1. p和q都为空,返回true
  2. p和q有一个为空,返回flase
  3. p和q都不为空,则判断他们的节点值是否相同,不相同返回false
  4. 上面都不满足,进行递归左右节点

注意:

  • 第一步和第二步不能互换,
  • 不用去管左子树和右子树是否为空的问题,因为递归下去以后就会帮你去判断

代码:

  1. bool isSameTree(struct TreeNode* p, struct TreeNode* q)
  2. {
  3. if(p==NULL && q==NULL)
  4. return true;
  5. if(p==NULL || q==NULL)
  6. return false;
  7. if(p->val != q->val)
  8. return false;
  9. return isSameTree(p->left,q->left) && isSameTree(p->right, q->right);
  10. }

3.另一棵树的子树

OJ题链接https://leetcode.cn/problems/subtree-of-another-tree/

 

 思路:

  • 这道题主要是用root的子树去和subRoot进行比较
  • 有了上面判断两个树是否相同的经验,我们只需要递归root来与subRoot比较即可
  • 注意递归时使用   ||   (或),在左子树或右子树有一个与subRoot相同的子树即为true

代码:

  1. bool isSameTree(struct TreeNode* p, struct TreeNode* q)
  2. {
  3. if(p==NULL && q==NULL)
  4. return true;
  5. if(p==NULL || q==NULL)
  6. return false;
  7. if(p->val != q->val)
  8. return false;
  9. return isSameTree(p->left,q->left) && isSameTree(p->right, q->right);
  10. }
  11. bool isSubtree(struct TreeNode* root, struct TreeNode* subRoot)
  12. {
  13. if(root==NULL)
  14. return false;
  15. if(isSameTree(root,subRoot))
  16. return true;
  17. return isSubtree(root->left,subRoot) || isSubtree(root->right,subRoot);
  18. }

4.反转二叉树

OJ题链接icon-default.png?t=N2N8https://leetcode.cn/problems/binary-tree-preorder-traversal/description/

思路:

  • 可根据后序遍历的想法,
  • 先遍历每一个节点,如果有节点时NULL,直接返回root
  • 不为NULL,继续递归遍历左子树,
  • 然后再遍历右子树
  • 最后将左子树和右子树进行交换

代码:

  1. struct TreeNode* invertTree(struct TreeNode* root)
  2. {
  3. if(root==NULL)
  4. return root;
  5. else
  6. {
  7. invertTree(root->left);
  8. invertTree(root->right);
  9. struct TreeNode* mp;
  10. mp=root->left;
  11. root->left=root->right;
  12. root->right=mp;
  13. }
  14. return root;
  15. }

5.对称二叉树

OJ题链接https://leetcode.cn/problems/symmetric-tree/

 思路:

  • 用左子树的左和右子树的右进行比较,
  • 先判断root是否为NULL,
  • 建立一个字函数,传左子树的指针和右子树的指针
  • 然后判断左子树和右子树是否为NULL,都为NULL返回true,有一个为NULL返回false
  • 都不为NULL,继续判断其值是否相同,不相同返回false,
  • 相同,继续递归,传递  左的左和右的右 && 左的右和右的左,进行递归

代码:

  1. bool _isSymmetric(struct TreeNode* L,struct TreeNode* R)
  2. {
  3. if(L->left==NULL && R->right==NULL)
  4. return true;
  5. if(L->left==NULL || R->right==NULL)
  6. return false;
  7. if(L->val!=R->val)
  8. return false;
  9. return _isSymmetric(L->left,R->right) && _isSymmetric(L->right,R->left);
  10. }
  11. bool isSymmetric(struct TreeNode* root)
  12. {
  13. if(root==NULL)
  14. {
  15. return true;
  16. }
  17. return _isSymmetric(root->left,root->right);
  18. }

6.二叉树的结构及遍历

OJ题链接https://www.nowcoder.com/practice/4b91205483694f449f94c179883c1fef?tpId=60&&tqId=29483&rp=1&ru=/activity/oj&qru=/ta/tsing-kaoyan/question-ranking

 思路:

看注释理解即可

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. struct TreeNode
  4. {
  5. char val;
  6. struct TreeNode* left;
  7. struct TreeNode* right;
  8. };
  9. //创建二叉树
  10. struct TreeNode* rebulidTree(char* str, int* i)
  11. {
  12. //= ‘#’直接返回,并将i++
  13. if(str[*i]=='#')
  14. {
  15. (*i)++;
  16. return NULL;
  17. }
  18. //不为‘#’首先malloc一个新的节点,并让root->val指向数组中对应下标位置的值
  19. struct TreeNode* root=(struct TreeNode*)malloc(sizeof(struct TreeNode));
  20. root->val = str[(*i)++];
  21. //递归左子树和右子树
  22. root->left = rebulidTree(str, i);
  23. root->right = rebulidTree(str, i);
  24. return root;
  25. }
  26. //中序遍历
  27. void InOrder(struct TreeNode* root)
  28. {
  29. if(root==NULL)
  30. return;
  31. InOrder(root->left);
  32. printf("%c ",root->val);
  33. InOrder(root->right);
  34. }
  35. int main()
  36. {
  37. char str[100];
  38. scanf("%s",str);
  39. int i=0;
  40. //这里传参一定一定要传地址,因为在递归过程中虽然i++过了,
  41. //但只是在局部的栈帧中,返回之后栈帧销毁,i还是不会变的
  42. struct TreeNode* root = rebulidTree(str,&i);
  43. InOrder(root);
  44. return 0;
  45. }

扩展:如何判断是不是完全二叉树、二叉树的销毁

1)判断是不是完全二叉树

思路:

  • 和层序遍历的思想一样,利用队列的先进先出进行
  • 如果是完全二叉树,在出队列,出到NULL时队列后面的元素应全为空
  • 如果不是完全二叉树,在出队列,出到NULL时,队列后面的元素会有不为空的情况

  • 我们可以加入一个flag做个判断标志,在第一次遇到NULL是,将flag变为false

  • 在只会再遇到不为空的元素时,如果flag为false,直接返回false

 代码如下:

  1. //判断二叉树是否为完全二叉树:
  2. bool isCompleteTree(BTNode* root)
  3. {
  4. BTNode* queue[1000]; //直接用树的结构来生成一个队列(只用到data变量,不用到左右孩子)
  5. int head = 0, tail = 0; //head即队列的头节点,用来出数据,tail即队列的尾结点,用来入数据
  6. bool flag = false; // 存储是否出现过空节点的标记
  7. queue[tail++] = root; //先让队列的头=树的根节点
  8. while (head < tail)
  9. {
  10. BTNode* curNode = queue[head++];
  11. //在第一次遇到NULL的时候,用flag进行记录
  12. if (curNode == NULL)
  13. flag = true;
  14. else
  15. {
  16. if (flag) // 如果之前出现过空节点,说明当前节点不是完全二叉树的节点
  17. return false;
  18. queue[tail++] = curNode->left;
  19. queue[tail++] = curNode->right;
  20. }
  21. }
  22. return true;
  23. }

2)二叉树的销毁

思路:递归进行销毁,和后序遍历类似

  1. void destroyTree(BTNode* root)
  2. {
  3. if (root == NULL)
  4. return;
  5. destroyTree(root->left);
  6. destroyTree(root->right);
  7. free(root);
  8. }

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

闽ICP备14008679号