树节点包含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。
如果您知道此问题的解决方案,请告知我们。
答案 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;
}