算法—判断整数序列是不是二元查找树的后序遍历结果
2015-09-08 18:18
288 查看
BST性质:节点左子树的任意节点小于根节点,右子树的任意节点大于等于根节点
后序遍历顺序:左——右——根
这个顺序很重要。由这个可以得知。对于任何一棵BST来说,后续遍历序列的最后一个数就是根节点。除此之外,左子树的所有节点在序列的前部,右子树的所有节点在序列的右部。注意到了这个,问题就没那么复杂了。
来分析这个后序序列:5,7,6,9,11,10,8
假设它是个BST的后续遍历序列。那8就是这棵BST的根节点。左子树节点为:5,7,6。右子树节点为:9,11,10。
进一步分析左子树和右子树。
对于左子树:5,7,6。根节点为6,左子树为5。右子树为7。
对于右子树:9,11,10。根节点为10,左子树为9,右子树为11。
因此这个BST为:
8
↙ ↘
6 10
↙ ↘ ↙ ↘
5 7 9 11
再来考虑后序序列:7,4,6,5。
同样假设它是一棵BST。那么5就是根节点。由于左子树节点都比根节点的小,且分布在序列前部。但是序列第一个节点为7,所以如果BST成立,则这棵BST的根节点没有左子树。因此右子树节点就是7,4,6。但是,由于右节点都大于或等于根节点。7,4,6明显不满足。因此这个序列不可能构成一棵BST。
总结一下。其实算法的思路就是:
1. 从初始序列开始,通过最后一个节点(根节点)将序列分割为左子树部分和右子树部分。
2. 判断左子树部分的所有节点是否都小于根节点,判断右子树的所有节点是否都大于或等于根节点。
3. 如果2成立,则对左右子树进行递归(和快排很像)。否则算法停止。
4. 如果递归到叶子节点,算法都未停止则返回true。表示这个序列是某一BST的后序遍历序列。
代码如下:
如果是给出前序遍历的序列,其实就是根节点在最前面。算法的其他部分还是一样。至于给出中序遍历的序列,只要是递增的就行了~
如果有什么不对的地方欢迎指出。
后序遍历顺序:左——右——根
这个顺序很重要。由这个可以得知。对于任何一棵BST来说,后续遍历序列的最后一个数就是根节点。除此之外,左子树的所有节点在序列的前部,右子树的所有节点在序列的右部。注意到了这个,问题就没那么复杂了。
来分析这个后序序列:5,7,6,9,11,10,8
假设它是个BST的后续遍历序列。那8就是这棵BST的根节点。左子树节点为:5,7,6。右子树节点为:9,11,10。
进一步分析左子树和右子树。
对于左子树:5,7,6。根节点为6,左子树为5。右子树为7。
对于右子树:9,11,10。根节点为10,左子树为9,右子树为11。
因此这个BST为:
8
↙ ↘
6 10
↙ ↘ ↙ ↘
5 7 9 11
再来考虑后序序列:7,4,6,5。
同样假设它是一棵BST。那么5就是根节点。由于左子树节点都比根节点的小,且分布在序列前部。但是序列第一个节点为7,所以如果BST成立,则这棵BST的根节点没有左子树。因此右子树节点就是7,4,6。但是,由于右节点都大于或等于根节点。7,4,6明显不满足。因此这个序列不可能构成一棵BST。
总结一下。其实算法的思路就是:
1. 从初始序列开始,通过最后一个节点(根节点)将序列分割为左子树部分和右子树部分。
2. 判断左子树部分的所有节点是否都小于根节点,判断右子树的所有节点是否都大于或等于根节点。
3. 如果2成立,则对左右子树进行递归(和快排很像)。否则算法停止。
4. 如果递归到叶子节点,算法都未停止则返回true。表示这个序列是某一BST的后序遍历序列。
代码如下:
#include <iostream> using namespace std; template <class T> bool isBST(T *array,int size); template <class T> int rightPartPos(T *array,int size); int main() { int array1[7]={5,7,6,9,11,10,8}; cout<<isBST(array1,8)<<endl; int array2[4]={7,4,6,5}; cout<<isBST(array2,4)<<endl; return 0; } template <class T> bool isBST(T *array,int size) { //递归到根节点 if(size<=1) { return true; } //没有递归到根节点 else { //分割左右子树,返回值为右子树部分开始的位置 int pos=rightPartPos(array,size); //右子树部分的节点中存在小于根节点的节点 if(pos<0) { return false; } else { //遍历,检查左、右子树 return isBST(array,pos)&&isBST(array+pos,size-pos-1); } } } template <class T> int rightPartPos(T *array,int size) { T root=*(array+size-1); for(int i=0;i<size-1;i++) { //当遇到小于根节点的节点继续往后找 if(root>*(array+i)) { continue; } //第一个大于或等于根节点的节点 //此时i位置的节点就是右子树部分的第一个节点 else { //判断右子树部分的节点是否大于或等于根节点 for(int j=i+1;j<size-1;j++) { //右子树部分节点中存在小于根节点的节点。BST不成立 if(*(array+j)<root) { return -1; } } return i; //返回右子树开始的位置 } } return size-1; //表示没有右子树 }
如果是给出前序遍历的序列,其实就是根节点在最前面。算法的其他部分还是一样。至于给出中序遍历的序列,只要是递增的就行了~
如果有什么不对的地方欢迎指出。
相关文章推荐
- 使用C++实现JNI接口需要注意的事项
- 关于指针的一些事情
- AVL树-自平衡二叉查找树(Java实现)
- c++ primer 第五版 笔记前言
- share_ptr的几个注意点
- 动易2006序列号破解算法公布
- 文件遍历排序函数
- Ruby实现的矩阵连乘算法
- C#插入法排序算法实例分析
- Lua 学习笔记之C API 遍历 Table实现代码
- Lua中调用C++函数示例
- Lua教程(一):在C++中嵌入Lua脚本
- Lua教程(二):C++和Lua相互传递数据示例
- 超大数据量存储常用数据库分表分库算法总结
- C#数据结构与算法揭秘二
- C#冒泡法排序算法实例分析
- C#中遍历Hashtable的4种方法
- 算法练习之从String.indexOf的模拟实现开始
- C#算法之关于大牛生小牛的问题
- C++联合体转换成C#结构的实现方法