C 将级别顺序插入到二叉树中?

C 将级别顺序插入到二叉树中?,c,algorithm,data-structures,binary-tree,C,Algorithm,Data Structures,Binary Tree,假设给我们一个级别顺序遍历输出。如何从正确位置填充的数据构造二叉树 请注意,我并不是试图从给定的遍历输出中绘制树,而是从数组中读取遍历数据,然后通过实际的C代码填充二叉树 例如: 设a[]={a,B,C,D,E,F,G}//数组中的遍历输出 因此,级别顺序树将如下所示: A / \ B C / \ / \ D E F G 假设有这样一个树节点结构: typedef struct nod

假设给我们一个级别顺序遍历输出。如何从正确位置填充的数据构造二叉树

请注意,我并不是试图从给定的遍历输出中绘制树,而是从数组中读取遍历数据,然后通过实际的C代码填充二叉树

例如:

设a[]={a,B,C,D,E,F,G}//数组中的遍历输出

因此,级别顺序树将如下所示:

            A
           / \ 
          B   C
        / \  / \
       D   E F  G
假设有这样一个树节点结构:

typedef struct node
{
    char data;
    struct node* left;
    struct node* right;
}tree;
现在我尝试读取[]值并对该树进行编码,使其看起来像图表。有很多级别顺序遍历的例子,但是找不到任何与二叉树构造的实际编码相关的东西。这是一种“反向遍历”

另外,请注意,这不是家庭作业,尽管如果更多的人注意到这一点,我不会有任何问题

对于完整(或填充)二叉树,很容易将级别遍历转换为任何遍历,因为位置
n
的节点的子节点在数组为1索引时位于
2n
2n+1
,在数组为0索引时位于
2n+1
2n+2

因此,您可以轻松地使用该公式将其转换为您最喜欢的遍历顺序,以便将节点插入到树中(如预顺序)

e、 g.递归伪代码:

void fill( TreeNode* node, char a[], int arrayLength, int n ){
    // n is the position of the current "node" in the array
    if( n < arrayLength ){
        node->data = a[n];
        fill( node->left, a, arrayLength, 2n+1 );
        fill( node->right, a, arrayLength, 2n+2 );
    }
}
void fill(TreeNode*节点,字符a[],整数数组长度,整数n){
//n是当前“节点”在数组中的位置
if(n<阵列长度){
节点->数据=a[n];
填充(节点->左,a,排列长度,2n+1);
填充(节点->右侧,a,排列长度,2n+2);
}
}

这就像一个BFS,因此您可以使用队列

请注意,始终指定左子对象,然后紧接着指定右子对象。 因此,从包含根的队列开始。在每次迭代中,从队列中弹出节点,然后从数组(或流)中读取接下来的两个值。将第一个作为弹出节点的左子节点,并将其推入队列。然后让第二个成为正确的子对象,并将其推到队列中。依此类推,直到数组(或流)中没有元素为止。

一种可能的解决方案:

char a[SIZE] = {A,B,C,D,E,F,G}; 
    node* func(int index){
        if(index < SIZE){
            node *tmp = new node();
            tmp->data = a[index];
            tmp->left = func(2*index + 1);
            tmp->right = func(2*index + 2);
        }
        return tmp;
    }

如果使用一些额外的存储,您可以以迭代的方式非常容易地完成这项工作,从而节省递归解决方案的调用开销。这就是我要做的:

node* theTree (char[] a, int arraylength) {
   if (arraylength == 0) return NULL;

   node** nodes = new node*[arraylength];
   nodes[0] = new node();
   nodes[0]->data = a[0];

   for (int i = 0, j = 0; TRUE ; j++) {
      if (++i >= arraylength) return nodes[0];

      nodes[i] = new node();
      nodes[i]->data = a[i];
      nodes[j]->left = nodes[i];

      if (++i >= arraylength) return nodes[0];

      nodes[i] = new node();
      nodes[i]->data = a[i];
      nodes[j]->right = nodes[i];
   }
}

可能的改进包括:通过在i>arraylength/2时覆盖指针数组的一部分,将所需的内存减少2倍,并可能一次预先分配数组中的所有节点(尽管此时需要小心解除分配).

在我看来,最简单的机制应该是将传入的数据存储到数据库中。传入数据是否适合堆属性?还是这棵树是二叉搜索树?奇怪。。。通常二叉树是根据一些比较来填充的。这里显然不是这样。几乎总是有多棵树需要从一个级别顺序遍历中构造。无法保证创建遍历的确切树将再次生成。@DeepYellow,不,二叉树每个节点最多有2个子树。二元搜索树对节点进行排序。@巴特,我意识到树是二元的,不需要排序就可以满足定义。我的观点是,在没有排序要求的情况下使用二进制结构是不寻常的。我从来没有遇到过实际应用,是吗?谢谢。递归移除绝对是一件好事,但目前对我来说并不是必需的——代码紧凑性现在就可以了。
node* theTree (char[] a, int arraylength) {
   if (arraylength == 0) return NULL;

   node** nodes = new node*[arraylength];
   nodes[0] = new node();
   nodes[0]->data = a[0];

   for (int i = 0, j = 0; TRUE ; j++) {
      if (++i >= arraylength) return nodes[0];

      nodes[i] = new node();
      nodes[i]->data = a[i];
      nodes[j]->left = nodes[i];

      if (++i >= arraylength) return nodes[0];

      nodes[i] = new node();
      nodes[i]->data = a[i];
      nodes[j]->right = nodes[i];
   }
}