Given BT: [1] [2] [3] [4] [5] [6] [7] [8] [9] [10] [11] [12] [13] [14] [15]ZigZag order of BT in DLL: [1] [3] [2] [4] [5] [6] [7] [15] [14] [13] [12] [11] [10] [9] [8]
这是我的伪代码:
DLLNode* ConvertBTToZigZgDLL(Node* root)
{
DLLNode* start=createDLLNode(root->data);
DLLNode* tail=start;
Stack<Node> stack1, stack2;
stack1.push(root->left);
stack1.push(root->right);
while( !stack1.Empty() || !stack2.Empty() )
{
while(stack1.HasElement())
{
Node* temp=stack1.Pop();
stack2.push(temp->right);
stack2.push(temp->left);
tail=Attach(tail,createDLLNode(temp->data));
tail=tail->next;
}
while(stack2.HasElement())
{
Node* temp=stack2.Pop();
stack1.push(temp->left);
stack1.push(temp->right);
tail=Attach(tail,createDLLNode(temp->data));
tail=tail->next;
}
}
return start;
} 这里是TimeComplexity O(N),其中N是给定二进制树中的节点数。
DLLNode* Attach(DLLNode* source, DLLNode* dest)
{
source.Next=dest;
dest.prev=source;
return source;
}
DLLNode* CreateDLLNode(int data)
{
DLLNode* res=malloc(sizeof(struct DLLNode));
res->data=data;
res->prev=NULL;
res->next=NULL;
return res;
}
我只想知道我的代码的逻辑有什么问题。
其中一位朋友说上面的代码不会工作而且错了。我无法找到我的逻辑失败的任何用例(排除空检查/空/空节点)
只需检查我的代码的逻辑并告诉我。
我的逻辑很简单:使用2个堆栈。在stack1中,我总是首先推动Left孩子,然后推动右孩子,在stack2中我总是先将正确的孩子推到第二位,然后将孩子推到第二位。最初加载stack1而stack1非空弹出并在stack2中推送相应的右/左子节点。对于上面的例子,我的堆栈状态应该像s1-B [2,3] T s2-B [7,6,5,4] T s1-B [8,9,10,11,12,13,14, 15] T B-stack底部T-Stack顶部。请再次检查。感谢。
答案 0 :(得分:1)
另一个问题已经涵盖了这一点。
答案 1 :(得分:1)
算法:
使用修改后的BFS算法,而不是单个fifo队列使用两个堆栈stack1
用于包含从右到左访问的级别中的节点,而stack2
包含要从左到右访问的节点。
列表使用根节点初始化,第一级(最接近根)存储在stack1
中。因此,第一次通过stack1
将以适当的顺序拉出第一级。
对于一般案例证明,假设stack1
中的元素以正确的顺序存储,从stack1
拉出N级节点可确保按从右到左的顺序处理它们。对于每个如此处理的节点,子树在第一个右侧存储在stack2
中,然后在左侧存储。这保证了对于级别N + 1,从stack2
检索的节点列表具有从左到右的顺序。当级别N上没有更多节点时,while
循环完成。此时从stack2
中提取节点将从左到右依次从级别N + 1中检索所有节点。
相反,当从每个从左到右的级别从stack2
拉出节点时,将子节点存储在stack1
的第一个左侧,然后是右侧,确保在下一次迭代中将它们拉出时从右到左的顺序。
所以基本上算法证明是合理的。现在这不能确保实现。特别是你要将所有NULL指针添加到堆栈中,这意味着你将检索它们,然后尝试通读它们。