L2-004 这是二叉搜索树吗?
-
一棵二叉搜索树可被递归地定义为具有下列性质的二叉树:对于任一结点,
-
其左子树中所有结点的键值小于该结点的键值;
-
其右子树中所有结点的键值大于等于该结点的键值;
-
其左右子树都是二叉搜索树。
所谓二叉搜索树的“镜像”,即将所有结点的左右子树对换位置后所得到的树。
给定一个整数键值序列,现请你编写程序,判断这是否是对一棵二叉搜索树或其镜像进行前序遍历的结果。
-
-
输入格式
输入的第一行给出正整数 N(≤1000)。随后一行给出 N 个整数键值,其间以空格分隔。
-
输出格式
如果输入序列是对一棵二叉搜索树或其镜像进行前序遍历的结果,则首先在一行中输出
YES
,然后在下一行输出该树后序遍历的结果。数字间有 1 个空格,一行的首尾不得有多余空格。若答案是否,则输出NO
。 -
输入样例1
7 8 6 5 7 10 8 11
-
输出样例1
YES 5 7 6 8 11 10 8
-
输入样例2
7 8 10 11 8 6 7 5
-
输出样例2
YES 11 8 10 7 5 6 8
-
输入样例3
7 8 6 8 5 10 9 11
-
输出样例3
NO
-
解题思路:
根据二叉搜索树的特性用递归来构造树,我们先看正常的树(没有镜像的树),首先对于一个序列,包括后面递归传进去的序列,该序列的起始点A肯定是该子树的根结点,在从这个起始点A(根结点)的下一个结点B开始遍历,遍历到该子树的结尾,找到第一个比该根结点大或者等于的点C,这个点C包括他后面的就是右子树,前面的不包括C和A就是该根结点的左子树。切记,找到之后,break出来,继续验证一下后面的结点是否再出现比根结点小的情况,若出现了,说明该子树压根就不是二叉搜索数,此时可以用一个全局标记来标记这个情况;若没有发现则就进行下一轮的递归。
对于镜像的树,不需要把他翻转回去,直接输出这个镜像树的后序遍历结果就好。
-
代码
#include <iostream> using namespace std; int A[1010]; // 判断是不是二叉搜索树(正常+镜像) int flag = 0; // count 为了在最后输出后序遍历时,不输出最后一个空格。 int count = 0; int N; typedef struct TNode { int data; TNode *lchild, *rchild; } TNode, *Tree; int main() { Tree CreateABinarySearchTree(int l, int r, int len); Tree CreateABinarySearchTreeReverse(int l, int r, int len); void Traverse(TNode * T); cin >> N; int i; for (i = 1; i <= N; i++) { cin >> A[i]; } TNode *T1 = CreateABinarySearchTree(1, N, N); // 正常的树不满足二叉搜索树的性质 if(flag==-1) { // 镜像树也不符合镜像二叉树搜索数的性质 TNode *T2 = CreateABinarySearchTreeReverse(1, N, N); if(flag==1) { cout << "NO" << endl; } // 符合镜像 else { // cout << "zhelima" << endl; cout << "YES" << endl; Traverse(T2); } } // 符合正常 else if(flag == 0) { cout << "YES" << endl; Traverse(T1); } return 0; } // 正常的二叉搜索数进行判断。 Tree CreateABinarySearchTree(int l, int r, int len) { // cout << "递归了几次?" << endl; if (len <= 0 || flag == -1) { return NULL; } TNode *T = new TNode; int root = A[l]; T->data = root; int i; int find = 0; int mid = l+1; int newLen = 0; // 找到第一个比他大或者等于的结点。 /* 要是找不到比他大的怎么办?可以分成两种情况进行讨论。 1. 传进来的len > 1,但就是没有任何数字大于等于根结点,此时就没有右子树了,全部都是左子树,只要将mid=r+1即可 2. 传进来的len = 1,此时循环根本执行不了,直接下一次递归返回NULL,这个结点就是个叶子结点,此时mid=r+1,l=r,newLen=0; */ for (i = l + 1; i < len + l; i++) { if (A[i] >= root) { mid = i; find = 1; newLen = mid - l - 1; break; } } if(find==1) { for (i = mid + 1; i < len + l; i++) { if (A[i] < root) { flag = -1; return NULL; } } } else { mid = r + 1; newLen = mid - l - 1; } T->lchild = CreateABinarySearchTree(l + 1, mid - 1, newLen); T->rchild = CreateABinarySearchTree(mid, r, len - newLen - 1); return T; } // 镜像的处理 Tree CreateABinarySearchTreeReverse(int l, int r, int len) { if (len <= 0 || flag == 1) { return NULL; } TNode *T = new TNode; int root = A[l]; T->data = root; int i; int find = 0; int mid = 0; int newLen = 0; for (i = l + 1; i < len + l; i++) { if (A[i] < root) { mid = i; newLen = mid - l - 1; find = 1; break; } } if(find==1) { for (i = mid + 1; i < len + l; i++) { if (A[i] >= root) { flag = 1; return NULL; } } } else { mid = r + 1; newLen = mid - l - 1; } T->lchild = CreateABinarySearchTreeReverse(l + 1, mid - 1, newLen); T->rchild = CreateABinarySearchTreeReverse(mid, r, len - newLen - 1); return T; } void Traverse(TNode *T) { if (T == NULL) { } else { Traverse(T->lchild); Traverse(T->rchild); cout << T->data; count++; if(count<N) { cout << " "; } } }