给定一个序列,我们需要判断此序列是否为某个二叉搜索树的后序遍历序列,题目在二叉搜索树的后序遍历
- 二叉搜索树的特点:中序遍历(左->根->右)是一个递增的序列,因此在后序遍历(左->右->根),我们可以判断根的位置,并判断左是否全部小于根,右是否全部大于根,一直判断直到整个序列被遍历
- 使用left和right指向需要判断的序列的左端点和右端点,根结点就是right指向的值
bool isPost(vector<int>& postorder,int left,int right){
if(left>=right) return true; //如果遍历完 直接返回true
int index=0; //index记录左树和右数的分段结点
int root=postorder[right]; //根结点的值为right指向的值
while(postorder[index]<root){ //判断左子树是否全部小于根
index++;
}
int temp=index+1; //右子树的起点
while(temp<right){ //遍历右子树
if(postorder[temp]<root){ //右子树的值要全部大于root 否则返回false
return false;
}
temp++;
}
return isPost(postorder,left,index-1)&&isPost(postorder,index,right-1); //分治,继续向下递归
}
bool verifyPostorder(vector<int>& postorder) {
int n=postorder.size();
return isPost(postorder,0,n-1);
}
给定树的中序遍历结果和先序遍历结果,求树的后续遍历结果:
void post(string &inor, string &pre) {
if (pre.size() == 0) return;
char root = pre[0]; //根结点是先序遍历序列的第一个值
int k = inor.find(root); //找到根结点在中序遍历序列中的位置
pre.erase(pre.begin()); //删去根结点
string leftpre = pre.substr(0, k); //求左子树的先序遍历
string rightpre = pre.substr(k); //求右子树的先序遍历
string leftinor = inor.substr(0, k); //求左子树的中序遍历
string rightinor = inor.substr(k + 1); //求右子树的中序遍历
post(leftinor, leftpre); //递归左子树的中序和先序序列
post(rightinor, rightpre);//递归右子树的中序和先序遍历
cout << root; //记录后序遍历的值
}
int main() {
string inor, pre;
cin >> inor >> pre;
post(inor, pre);
return 0;
}