关于树数据结构的问题:我们如何填充所有树节点的所有inorder后继指针?

时间:2010-12-01 03:10:18

标签: algorithm data-structures recursion tree

树节点包含3个指针* left,* right和* Successor。

Struct node{
     int data;
     struct node *left;
     struct node *right;
     struct node *successor; 
}; 


        A
       /  \
      B    C
     / \  / \
    D   E F  G

INORDER Traversal: DBEAFCG * 注意: * A inorder继承者是F,C和G.

  **Function prototype:** void  FillSuccessorNodes( struct node *root);

给我们树的根节点,我们需要填充所有节点的后继指针。

案例1)一些后继指针可能是 NULL 。在这种情况下,您必须使用即时Inorder Successor填充该指针。

示例:如果A->; Successor == NULL,则填写A-> Successor = F

案例2)一些后继指针可能已指向正确的后继者。这种情况你不需要修改后继指针。

示例:1)A-> successor = F有效

     2) A->successor = C is valid

     3) A-successor = G is valid  . All these three cases you no need to modify successor pointer since these already pointing to correct successor nodes.  

情况3)一些后继指针是 not NULL ,但这些指针指向INVALID后继,即它可能是顺序继承或一些垃圾值。在这种情况下,您必须使用直接后继节点填充这些节点。

示例:

     1) A->successor = B is invalid since B is not successor node , so we have to correct it to A->successor = F.

     2) A->successor = 0x23237463478 is invalid since it is pointing to garbage value. So we we have to correct it to A->successor = F. 

1)采访者问我O(n)时间复杂度的时间有效解决方案。允许额外空间。 2)她给了一些提示,即我们可以使用HASHing。

如果您知道此问题的解决方案,请告知我们。

2 个答案:

答案 0 :(得分:1)

这个问题和提示似乎对我有误导性。因为你必须检查所有节点以检查它们的后继者是否无效,并且因为你必须计算后继者以知道无效的含义,所以你也可以使用标准的O(n)inorder遍历,例如:

#include <utility>
using namespace std;

typedef pair<node*, node*> node_pair;

node_pair setInOrderSuccessors(node* root)
{
    node_pair result(root, root);

    if (root->left) {
        const node_pair pair = setInOrderSuccessors(root->left);
        result.first = pair.first;
        pair.second->successor = root;
    }

    if (root->right) {
        const node_pair pair = setInOrderSuccessors(root->right);
        result.second = pair.second;
        root->successor = pair.first;
    }

    return result;
}

void  FillSuccessorNodes(node *root)
{
    const node_pair pair = setInOrderSuccessors(root);
    pair.second->successor = 0;
}

答案 1 :(得分:1)

只需对遍历进行一次小修改,你必须记住前一个并获得前任 - &gt; successor = current。

stack<node*> s;
node* t = root ,*pred=NULL;
while(true)
{
    if(t){
            s.push(t);
            t= t->left; 
            continue;
    }           
    if(s.empty()) { break;}
    t= s.top();
    if(NULL != pred && pred->succesor != t)
    {
        pred->succesor = t;     
    }
    pred  = t; 
    s.pop();        
    cout<<t->c;
    t= t->right; 
}