PAT题库-1064. Complete Binary Search Tree (30)
1064. Complete Binary Search Tree (30)
A Binary Search Tree (BST) is recursively defined as a binary tree which has the following properties:
- The left subtree of a node contains only nodes with keys less than the node's key.
- The right subtree of a node contains only nodes with keys greater than or equal to the node's key.
- Both the left and right subtrees must also be binary search trees.
A Complete Binary Tree (CBT) is a tree that is completely filled, with the possible exception of the bottom level, which is filled from left to right.
Now given a sequence of distinct non-negative integer keys, a unique BST can be constructed if it is required that the tree must also be a CBT. You are supposed to output the level order traversal sequence of this BST.
Input Specification:
Each input file contains one test case. For each case, the first line contains a positive integer N (<=1000). Then N distinct non-negative integer keys are given in the next line. All the numbers in a line are separated by a space and are no greater than 2000.
Output Specification:
For each test case, print in one line the level order traversal sequence of the corresponding complete binary search tree. All the numbers in a line must be separated by a space, and there must be no extra space at the end of the line.
Sample Input:10 1 2 3 4 5 6 7 8 9 0Sample Output:
6 3 8 1 5 7 9 0 2 4
这道题考察的点是二叉搜索树和完全二叉树。刚开始我第一反应就是完全二叉树的性质:用数组存储的话,父节点下标为i,左孩子为2i,右孩子为2i+1。而一个完全二叉搜索树的最小节点肯定在最左边。我一开始的想法是用数组存储,找到最左边那个位置,放进去0,然后找到0的父节点,放1,再放右节点的2,再往上一直放,但是当时没想到用递归,觉得这样写会很麻烦,所以放弃了。
接着我用了最普通的链式方法建树,然后层序遍历输出。不得不说,链式方法建树很繁琐,我调试了很久才通过。具体思路是,先把输入数据放在一个vector里面,然后排序,从小到大排。然后找出整个树的根节点的下标(找的方法是先计算左子树有几个节点),再递归,在左子树再建树。这样非常麻烦,写递归的时候很容易出错。
后来AC之后在网上搜了搜,发现有非常好的做法。其实我一开始的想法类似,但是没有更进一步去想。一个完全二叉搜索树的中序遍历的结果就是递增排列的,那么我们采用中序遍历的方法去建树(即遍历的时候,visit操作是给节点赋值!)。这种逆向思维是我之前完全没想到的,这次学习了。总之就是,采用中序遍历的方法,利用完全二叉树的父子节点关系去建树,最后把数组按序输出即可。
下面我把两种方法的代码都贴上来。很明显,第一段代码明显比第二段简单得多得多得多得多!!!
1 #include<iostream> 2 #include<vector> 3 #include<algorithm> 4 using namespace std; 5 6 int N; 7 int pos=0; 8 int *tree; 9 vector<int> vec; 10 11 void build(int n) 12 { 13 if (n>N) return; 14 else 15 { 16 build(n*2); 17 tree[n] = vec[pos++]; 18 build(n*2+1); 19 } 20 } 21 22 int main() 23 { 24 int element; 25 cin >> N; 26 tree = new int [N+1]; 27 //输入元素并排序 28 for (int i=0;i<N;i++) 29 { 30 cin >> element; 31 vec.push_back(element); 32 } 33 sort(vec.begin(),vec.end()); 34 35 build(1); 36 cout << tree[1]; 37 for (int i=2;i<=N;i++) 38 cout << ' ' << tree[i]; 39 return 0; 40 }
1 #include<iostream> 2 #include<vector> 3 #include<cmath> 4 #include<queue> 5 #include<algorithm> 6 using namespace std; 7 8 typedef struct node* tree; 9 struct node 10 { 11 int data; 12 tree left; 13 tree right; 14 }; 15 16 tree BuildTree (tree,int,unsigned,unsigned); 17 int FindRoot(int,int); 18 void LevelOrderTraversal(tree T); 19 vector<int> vec; 20 21 int main() 22 { 23 int N,element; 24 cin >> N; 25 26 //输入元素并排序 27 for (int i=0;i<N;i++) 28 { 29 cin >> element; 30 vec.push_back(element); 31 } 32 sort(vec.begin(),vec.end()); 33 34 unsigned b=0,e=vec.size()-1; 35 36 int root=FindRoot(N,0); 37 tree T = nullptr; 38 T=BuildTree(T,root,b,e); 39 40 LevelOrderTraversal(T); 41 42 return 0; 43 } 44 45 int FindRoot(int N,int base) 46 { 47 int level=int(log(double(N))/log(2.0))+1; //共有这么多层 48 int root=1; 49 if (N == 1) 50 root = 0; 51 else if (N == 2) 52 root = 1; 53 else if (N==3) 54 root = 1; 55 else 56 if (N-(pow(double(2),double(level-1))-1) > pow(double(2),double(level-2)) )//左子树满了 57 root = pow(double(2),double(level-1))-1; 58 else 59 root = pow(double(2),double(level-2))-1+N-(pow(double(2),double(level-1))-1); 60 return root+base; 61 } 62 63 tree BuildTree(tree T,int root,unsigned b,unsigned e) 64 { 65 //cout << b << e << endl; 66 if (e==b) 67 { 68 T=new node; 69 T->data = vec[b]; 70 T->left = nullptr; 71 T->right = nullptr; 72 } 73 else 74 { 75 T = new node; 76 T->data = vec[root]; 77 T->left = BuildTree(T,FindRoot(root-b,b),b,root-1); 78 if (e!=root) 79 T->right= BuildTree(T,FindRoot(e-root,root+1),root+1,e); 80 else 81 T->right = nullptr; 82 } 83 return T; 84 } 85 86 void LevelOrderTraversal(tree T) 87 { 88 bool flag=true; 89 queue<tree> Q; 90 if (!T) return; 91 Q.push(T); 92 while (!Q.empty()) 93 { 94 if (flag) 95 { 96 cout << Q.front()->data; 97 flag = false; 98 } 99 else 100 cout << ' ' << Q.front()->data; 101 if (Q.front()->left) 102 Q.push(Q.front()->left); 103 if (Q.front()->right) 104 Q.push(Q.front()->right); 105 Q.pop(); 106 } 107 }