二叉树进阶

目录 01 中序先序确定树 03 先序后续确定树 05 二叉树题目 02 中序后续确定树 04 二叉搜索树 06 总结

01章 中序先序 确定树 1.还原二叉树: 我们能不能通过知道二叉树的序列得到这颗二叉树呢? 需要满足什么条件呢? 我们把通过二叉树序列得到二叉树的过程称为还原二叉树。 在我们的二叉树中: 已知先序和中序可以得到二叉树。 已知后序和中序可以得到二叉树。 已知先序和后序并不能得到二叉树。 1.先根据线序遍历序列确定根结点,即第一个结点(根左右)。 根据根节点再中序遍历序列中分别分割出左子树和右子树(左根右:根节点左侧为 左子树,右侧为右子树)。 对左子树和右子树分别递归使用相同的方法继续分解 例: 先序序列 a bcde fghij ; 中序序列 cbed a hgijf 对于根节点a,先序、中序序列可以分别分解为下图两棵树: 对于每个节点的左子树、右子树,按照同样的算法逐步分解,最后可以确认一棵 唯一树。

void creat(node * &root,string a,string b){ if(a=="") root=NULL; else{ root=new node; root->data=a[0]; int k=b.find(a[0]); creat(root->left,a.substr(1,k),b.substr(0,k)); creat(root->right,a.substr(k+1,b.size()-k),b.substr(k+1,b.size()-k)); } } 

或者我们可以传作为 左子树的先序的左右两个断点,左子树中序的左右两个端点。 右子树的先序的左右两个断点,右子树中序的左右两个端点。 假设当前 树 先序 在 原数组 中的 位置是 l1 到 r1 当前 树 中序 在 原数组 中的 位置是 l2 到 r2 那么 当前树的根节点一定是 a[l1] 找到 a[l1]在 b 中的位置 k 。 或者我们可以传作为 左子树的先序的左右两个端点: l1+1, (k-l2)+l1 左子树中序的左右两个端点: l2,k-1 右子树的先序的左右两个端点: (k-l2)+l1+1,r1 右子树中序的左右两个端点: k+1,r2 所以对于这样一个分治的过程,我们用递归就可以实现了():

void build(node * & root,int l1,int r1,int l2,int r2){ if(l1data=a[l1]; int k=b.find(a[l1]); build(root->left,l1+1,(k-l2)+l1,l2,k-1); build(root->right,(k-l2)+l1+1,r1,k+1,r2); } }

void LRD(node * &T){ if(T!=NULL){ LRD(T->lef t); LRD(T->right); coutdata; } }

02章 中序后序 确定树 1.后序遍历的最后一位即是二叉树的根节点。 2.然后再中序遍历找到根结点,根节点左边的所有序列便是左子树的中序遍历结果 ,右边的所有序列便是右子树中序遍历结果。 3.在后序遍历中找到对应的左子树,右子树。 4.在左右子树的先序和中序结果中继续重复1 , 2 ,3步骤,便可还原二叉树。 03章 先序后序 确定树 我们思考一个问题,如果我只知道先序和后序我能得到二叉树的什么性质呢? 所有这些二叉树都有着相同的前序遍历和后序遍历,但中序遍历却不相同。 我们发现: 只有一个儿子 的节点 才会在知道 前序后序 的情况下有不同的中序遍历, 并且由两种情况,所以将题目转化成找 只有一个儿子的节点个数。 那么我们又思考: 作为先序遍历,根左右,如果只有一个子节点,那么这个子节点一定是在 根节点的右边。 作为后序遍历,左右根,如果只有一个子节点,那么这个子节点一定是在 根节点的左边。

所以答案就出来了,一旦出现: a[i] == b[j] 并且 a[i+1] == b[j-1]的时候就说明我们找到了 这个 i 就是只有一个孩子的节点。 那么答案就是 2^cnt 颗树 cnt 就代表了只有一个子节点的个数。 scanf("%s",a); scanf("%s",b); for(int i=0;i

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值