题目:输入一个整数数组,判断该数组是不是某二元查找树的后序遍历的结果。如果是返回true,否则返回false。
例如输入5、7、6、9、11、10、8,由于这一整数序列是如下树的后序遍历结果:
则输出:yes
又如输入7、4、6、5 ;因没有对应的二元查找树的后序遍历是次序列,则输出no
简单的分析一下这道题:后序遍历也就是说最后的一个节点是根节点,二元查找树又要求它的左子树不大于(或不小于)根节点,右子树不小于(或不大于)根节点。
因此,思路也就来了:先把它的根节点拿出来,然后从首元素开始遍历,与根节点比较,直到找出大于根节点的元素来,然后再遍历后面的是否有小于根节点的元素(只考虑左子树不大于根节点,右子树不小于根节点一种情况)。因为小于根节点的一定都在左子树,大于根节点的都在右子树,若在右子树中找到小于根节点的元素,则说明这不是二元查找树,就可以返回,否则再递归已经划分好的左子树与右子树。
分析一下上面的输入int a[7] = {5、7、6、9、11、10、8 }
首先将a[last=6] = 8 取出,作为根节点,然后开始first=0开始到end=last - 1遍历数组a,当i=3时,a[3]=9 > 8则mid=3为分界,左边first-(mid-1)为左子树,右边mid-end为右子树,接着遍历右子树,因为没有小于根节点8的元素,因此,开始递归上述的左子树a[first-(mid-1)]与右子树a[mid-end]。如左子树,取出a[last=(mid-1)]=6作为根节点,然后从first=0开始到end=last-1=(mid-1)-1,与根节点a[last]=6比较,然后再划分左右子树。。。直到first=end为止或者出现右子树中存在小于根节点的元素。
#include<stdio.h> #include<stdlib.h> bool BTreeLast(int* a,int first,int last){ int i,mid; for(i = first; (i < last)&&(a[i] < a[last]); i++);//小于根的都是左子树 mid = i;//左右子树分界点 for(i = mid; (i < last)&&(a[i] >= a[last]); i++); if(i < last)//右子树未遍历完,则说明不是二叉查找树 retun false; if(first < mid - 1) if(!BTreeLast(a,first,mid - 1))//不符则退出 return false; if(mid < last - 1) if(!BTreeLast(a,mid,last - 1))//不符则退出 return false; return true; } int main(){//测试 int i,length; printf("输入元素个数"); scanf("%d",&length); int* a = new int(length); printf("输入%d个元素: ",length); for(i = 0; i < length; i++) scanf("%d", a + i); if(BTreeLast(a,0,length - 1)) printf("yes "); else printf("no "); delete[] a; return 0; }