数组二叉树

要求:

现给一串数字,按照顺序从根插入到二叉树中。但是插入的过程要注意,左子树的值要小于等于父节点,右子树的值要大于父节点。

例如,序列为1 3 4 2 3 0,插入对应的二叉树为

                      1

                   /       

                 0            3

                             /     

                           2         4

                            

                              3

建好二叉树后,从根开始输出每行数字,每层按照从左到右的顺序输出。

输入:

第一行为数字序列长度N(1≤N≤11)

接下来n个数字,每个数字大于等于0

输出:

整棵二叉树的数字。每个数字一个换行

样例输入:

1 3 4 2 3 0

样例输出:

0

2

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 }
原文地址:https://www.cnblogs.com/Arthas8086/p/12095005.html