蚬爷

PAT题库-1064. Complete Binary Search Tree (30)

1064. Complete Binary Search Tree (30)

时间限制
100 ms
内存限制
32000 kB
代码长度限制
16000 B
判题程序
Standard
作者
CHEN, Yue

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 0
Sample 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 }

 

 

posted on 2016-02-20 21:55  蚬爷  阅读(644)  评论(0编辑  收藏  举报