级别订单插入二叉树?

时间:2011-07-02 07:25:00

标签: c algorithm data-structures binary-tree

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

请注意,我不是要尝试从给定的遍历输出中绘制树,而是从数组中读取遍历数据,然后通过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;

现在我正在尝试读取[]值并对此树进行编码,使其看起来像图。有许多级别顺序遍历的例子,但是在二叉树构造的实际编码中找不到任何相关的东西。这有点像“遍历的逆转”。

另请注意,这不是家庭作业,但如果有更多人会注意到这一点我没有标记问题。 :)

4 个答案:

答案 0 :(得分:6)

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

请注意,您始终指定左孩子,然后立即分配正确的孩子。 所以从包含root的队列开始。在每次迭代时,从队列中弹出节点,然后从数组(或流)中读取接下来的两个值。使第一个成为弹出节点的左子节点并将其推入队列。然后使第二个成为正确的孩子并将其推入队列。依此类推,直到数组(或流)中没有任何元素。

答案 1 :(得分:5)

对于完整(或填充)二叉树,可以轻松将级别遍历转换为任何遍历,因为位置n处的节点的子项位于 2n并且当数组为1索引时为2n+1,当数组为0索引时为 2n+12n+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 );
    }
}

答案 2 :(得分:5)

一种可能的解决方案:

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;
    }

树的stacktrace:

                                     A->a[0]
          B->func(2*0 + 1)=[1]                              C->func(2*0 + 2)=[2]
D->func(2*1 + 1)=[3]    E->func(2*1 + 2)=[4]        F->func(2*2 + 1)=[5]     G->func(2*2 + 2)=[6]

答案 3 :(得分: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];
   }
}

可能的改进包括通过在i> 1之后重写指针数组的部分来将所需的存储器减少两倍。 arraylength / 2,并且可能自己在数组中一次性预分配所有节点(尽管你需要小心重新分配)。