数组二叉树
要求:
现给一串数字,按照顺序从根插入到二叉树中。但是插入的过程要注意,左子树的值要小于等于父节点,右子树的值要大于父节点。
例如,序列为1 3 4 2 3 0,插入对应的二叉树为
1
/ \
0 3
/ \
2 4
\
3
建好二叉树后,从根开始输出每行数字,每层按照从左到右的顺序输出。
输入:
第一行为数字序列长度N(1≤N≤11)
接下来n个数字,每个数字大于等于0
输出:
整棵二叉树的数字。每个数字一个换行
样例输入:
1 3 4 2 3 0
样例输出:
1
0
3
2
4
3
Hint:父节点的位置为i时,左子节点为i*2+1,右子节点为i*2+2.
先解释一下数组如何表示二叉树:
一个数组为a[10],那么它表示的完全二叉树为(下面数字只表示数组下标,不表示数组的值)
0
/ \
1 2
/ \ / \
3 4 5 6
/ \ /
7 8 9
这就是一个数组表示的完全二叉树。
完全二叉树就是除了最下面那一层外(这个图是第四层7 8 9)前面几层是满二叉树(度(子节点数)为0或2)
也就是说,我们用数组表示二叉树时,并不需要对数组进行什么操作,
只是我们意识上认为这个数组是个二叉树,然后按照二叉树来处理这个数组。
也就是数组下标遵循二叉树的规律。就比如左右子树和父节点的关系。
虽然说我们这道题结果不是完全二叉树,就像例题那样,
但是我们可以把它想像成值全为-1的完全二叉树,然后向-1的节点插入值。
思路分析:
由提示可以看出,这就像是一个哈希查找(按照一定规则映射到数组)
这个规则就是左子树小于等于父节点,右子树大于父节点。
而父节点和左右子树下标的关系值已经给了出来。
而节点的值非负,所以我们可以将目标数组全部赋为-1,以此来判断目标数组是否存有值。
所以这道题本质就是向空数组插入数据的过程。
输出的时候,我们需要的是值不为-1的节点
(我们创建了这个数组,按照提示的规则插入数据,其实就是把数组当成了完全二叉树)
所以按照我们插入的结果,按数组下标输出就行。
详细代码如下。(若结果出错,可能是target数组开的不够大)
1 1 #include<bits/stdc++.h> 2 2 using namespace std; 3 3 int main() 4 4 { 5 5 int n; 6 6 cin>>n; 7 7 int a[n]; //写入数据的数组 8 8 for (int i = 0; i < n; i++) cin>>a[i]; 9 9 int target[100]; //空数组,用来接受映射结果 10 10 target[0]=a[0]; //树根是第一个位置 11 11 for (int i = 1; i < 100; i++) target[i]=-1; //因为a[n]大于等于零 12 12 //所以我们可以把其他的数都赋为-1,来区分数组这个位置有没有存数 13 13 for (int i = 1; i < n; i++) //这里开始插入 14 14 { 15 15 int j=0; //从树根开始找位置 16 16 while(target[j]!=-1) //不等于-1的话说明这个位置已经插入数字了 17 17 { 18 18 if (a[i]<=target[j]) j=2*j+1; //判断大小,(小于等于父节点)检查左子树有没有插入 19 19 else j=2*j+2; //检查右子树 20 20 } 21 21 target[j]=a[i]; //找到位置后,赋值 22 22 } 23 23 int j=0; //开始从头开始找插入的数字 24 24 for (int i = 0; i < n; i++) //数组大小为n,所以找到n个即可 25 25 { 26 26 while (target[j]==-1) j++; //说明这个位置是空的,继续找 27 27 cout<<target[j]<<endl; //退出循环,说明找到了,把数字输出来 28 28 j++; //输出之后,继续找,所以j要递增 29 29 } 30 30 return 0; 31 31 }