关键词搜索

源码搜索 ×
×

【数据结构】二叉树经典习题

发布2022-04-17浏览2402次

详情内容

965. 单值二叉树

思路:

1.若树为空,则返回true,因为并不违反规则。

2.将根结点和左子树右子树的值做比较,若不相等就返回false.

3.递归实现先序遍历即可,即左子树比完再比右子树,且都得相等。

 

  1. bool isUnivalTree(struct TreeNode* root){
  2. //先序遍历
  3. if(root == NULL)
  4. return true;
  5. //判断==并没有多大的用处,判断相反可快速结束递归。
  6. if(root->left && root->val != root->left->val)//1.判断节点是否存在,2.判断值是否不相等。
  7. return false;
  8. if(root->right && root->val != root->right->val)
  9. return false;
  10. return isUnivalTree(root->left) && isUnivalTree(root->right);//左树 右树都得同时满足才可返回真
  11. }

100. 相同的树

在两棵树的比较,就是看对应节点是否存在且相等。

思路:1.若两棵树都为空,则返回true。

2.若两棵树对应节点有缺失,则返回false

3.递归,前序遍历即可。

  1. bool isSameTree(struct TreeNode* p, struct TreeNode* q){
  2. //同时为空树,返回真
  3. if(p == NULL && q == NULL)
  4. return true;
  5. //当只有其中一个为空时,返回假
  6. if(p == NULL || q == NULL)
  7. return false;
  8. //递归
  9. if(p->val != q->val)
  10. return false;
  11. //左树遍历完遍历右树,且对应的左右书必须完全相等
  12. return isSameTree(p->left,q->left) && isSameTree(p->right,q->right);
  13. }

对称二叉树

在比较两颗树是否相等的基础上,进行了小范围的改动。

这里,我们只需要比较根结点以下的根左子树和根右子树。

比较要注意:因为是镜面对称,所以比较的是左树的左子树与右树的右子树;

左树的右子树与右子树的左子树相比较。

调用相同的树的代码即可,

 

  1. bool _isSameTree(struct TreeNode* p, struct TreeNode* q){
  2. //同时为空树,返回真
  3. if(p == NULL && q == NULL)
  4. return true;
  5. //当只有其中一个为空时,返回假
  6. if(p == NULL || q == NULL)
  7. return false;
  8. //递归
  9. if(p->val != q->val)
  10. return false;
  11. //左树遍历完遍历右树,且对应的左右书必须完全相等
  12. return _isSameTree(p->left,q->right) && _isSameTree(p->right,q->left);
  13. }
  14. bool isSymmetric(struct TreeNode* root){
  15. //为空树
  16. if(root == NULL)
  17. return true;
  18. //调用相同树的代码
  19. return _isSameTree(root->left,root->right);
  20. }

二叉树的前序遍历

复习:前序遍历:根 - 左子树 - 右子树

总之还是递归分治的思想,但是,这道题又有点不同。

这道题要自己申请一个数组空间来存储数据,使用静态的数组会因为函数栈帧的缘故,当函数出了作用域时,就会被销毁,返回的值可能就根本”不存在“。而static修饰的静态局部变量,多次调用,就会出现数据覆盖的问题,最优解就是:在堆上开辟空间,那开多大的空间?

我们可以先遍历一遍二叉树,获得二叉树的节点个数,相应的代码及思路已经在之前的博客中提及过了。

思路:1.先序遍历的思想

2.递归求节点的个数。

2.动态开辟数组。

 

  1. int BTreeSize(struct TreeNode* root)
  2. {
  3. return root == NULL? 0:BTreeSize(root->left)+BTreeSize(root->right)+1;
  4. }
  5. void _preorder(struct TreeNode* root,int* a,int* pi)
  6. {
  7. if(root == NULL)
  8. return ;
  9. a[(*pi)++] = root->val;
  10. _preorder(root->left,a,pi);
  11. _preorder(root->right,a,pi);
  12. }
  13. int* preorderTraversal(struct TreeNode* root, int* returnSize){
  14. //确定树的大小
  15. *returnSize = BTreeSize(root);
  16. int* a = (int*)malloc(sizeof(int)*(*returnSize));
  17. int i =0;
  18. _preorder(root,a,&i);
  19. return a;
  20. }

二叉树的后序遍历

后序遍历:左子树 - 右子树 - 根

思路与上面的前序遍历一致

 

  1. int BTreeSize(struct TreeNode* root)
  2. {
  3. return root == NULL? 0:BTreeSize(root->left)+BTreeSize(root->right)+1;
  4. }
  5. void _preorder(struct TreeNode* root,int* a,int* pi)
  6. {
  7. if(root == NULL)
  8. return ;
  9. _preorder(root->left,a,pi);
  10. _preorder(root->right,a,pi);
  11. a[(*pi)++] = root->val;
  12. }
  13. int* postorderTraversal(struct TreeNode* root, int* returnSize){
  14. *returnSize = BTreeSize(root);
  15. int* a = (int*)malloc(sizeof(int)*(*returnSize));
  16. int i =0;
  17. _preorder(root,a,&i);
  18. return a;
  19. }

二叉树的中序遍历

  1. int BTreeSize(struct TreeNode* root)
  2. {
  3. return root == NULL? 0:BTreeSize(root->left)+BTreeSize(root->right)+1;
  4. }
  5. void _preorder(struct TreeNode* root,int* a,int* pi)
  6. {
  7. if(root == NULL)
  8. return ;
  9. _preorder(root->left,a,pi);
  10. a[(*pi)++] = root->val;
  11. _preorder(root->right,a,pi);
  12. }
  13. int* inorderTraversal(struct TreeNode* root, int* returnSize){
  14. *returnSize = BTreeSize(root);
  15. int* a = (int*)malloc(sizeof(int)*(*returnSize));
  16. int i =0;
  17. _preorder(root,a,&i);
  18. return a;
  19. }

另一棵树的子树

本质上就是寻找子树的问题,当大树的一个小树和所给定的小树的结构和值完全相等时,返回true

考虑调用判断两个数是否相同的函数代码,采用分治的思想,先跑完左子树寻找,再跑右子树寻找,期间若找到了,就直接返回true

主要还是分支的思想。

  1. bool _isSameTree(struct TreeNode* p, struct TreeNode* q){
  2. //同时为空树,返回真
  3. if(p == NULL && q == NULL)
  4. return true;
  5. //当只有其中一个为空时,返回假
  6. if(p == NULL || q == NULL)
  7. return false;
  8. //递归
  9. if(p->val != q->val)
  10. return false;
  11. //左树遍历完遍历右树,且对应的左右书必须完全相等
  12. return _isSameTree(p->left,q->left) && _isSameTree(p->right,q->right);
  13. }
  14. bool isSubtree(struct TreeNode* root, struct TreeNode* subRoot){
  15. if(root == NULL && subRoot == NULL)
  16. return true;
  17. if(root == NULL || subRoot == NULL)
  18. return false;
  19. //判断其是否为相同的树,找完左树找右树
  20. return _isSameTree(root,subRoot) || isSubtree(root->left,subRoot) || isSubtree(root->right,subRoot);
  21. }

二叉树遍历

思路:1)建树,递归分治建树。

2)传递参数时,要传递指针,传值调用,传递的是形参,形参的改变不会影响实参,所以递归时就会出错。

3)中序遍历,左子树 - 根 - 右子树

  1. #include<stdio.h>
  2. #include<stdlib.h>
  3. typedef struct BTreeNode
  4. {
  5. char data;
  6. struct BTreeNode* left;
  7. struct BTreeNode* right;
  8. }BTNode;
  9. BTNode* CreatTree(char *a, int *pi)//这里必须传递指针 pi
  10. {
  11. //递归方式创建树,那么就必须传址调用,而不是传值调用。
  12. //如果是‘#’就返回NULL,同时找数组下一位
  13. if(a[*pi] == '#')
  14. {
  15. (*pi)++;
  16. return NULL;
  17. }
  18. //创建树
  19. BTNode* root = (BTNode*)malloc(sizeof(BTNode));
  20. root->data = a[(*pi)++];
  21. root->left = CreatTree(a, pi);
  22. root->right = CreatTree(a, pi);
  23. return root;
  24. }
  25. void InOrder(BTNode* root)
  26. {
  27. if(root == NULL)
  28. return;
  29. InOrder(root->left);
  30. printf("%c ",root->data);
  31. InOrder(root->right);
  32. }
  33. int main()
  34. {
  35. char a[100];
  36. scanf("%s",a);
  37. //创建树
  38. int i = 0;
  39. BTNode* Tree = CreatTree(a,&i);
  40. InOrder(Tree);
  41. return 0;
  42. }

相关技术文章

点击QQ咨询
开通会员
返回顶部
×
微信扫码支付
微信扫码支付
确定支付下载
请使用微信描二维码支付
×

提示信息

×

选择支付方式

  • 微信支付
  • 支付宝付款
确定支付下载