[英]Iterative postorder traversal breaks at root node of tree
我實現了一種算法,用於迭代地打印二叉樹的后序遍歷。 整個算法都起作用,除了當它到達樹的根部時會進入無限循環。
有人可以指出我正確的方向嗎? 我已經在這個問題上停留了2天了。
void postorder_nonrec_2(treenode *root)
{
stack_t *s;
stack_init(&s, 100);
treenode *temp = root;
while(1)
{
while(root)
{
push(s, root);
root = root -> left;
}
if(stack_isEmpty(s))
break;
if(!top(s) -> right)
{
root = pop(s);
printf("%d ", root -> data);
if(root == top(s) -> left)
{
root = top(s) -> right;
}
else if(root == top(s) -> right)
{
printf("%d ", pop(s) -> data);
root = NULL;
}
}
else
{
root = top(s) -> right;
}
}
}
也許在您使用的測試用例中,僅在根部存在一個無限循環,但是我認為該無限循環也可能發生在樹的其他位置,具體取決於特定的樹。
我認為問題是,當右側有子級時,您不會正確繼續彈出堆棧。
考慮一個簡單的示例,其中我們的根節點1的左子節點為0,右子節點為2,並假設2的右節點為3。
在第一個循環中,我們將1和0壓入堆棧。 然后0沒有左子節點,因此root變為null。 堆棧不為空,因此我們繼續。 0在堆棧的頂部,並且沒有合適的子級,因此我們輸入if語句的第一個分支。 然后我們打印出0,因為0是1的左孩子-1現在是堆棧的頂部-根變成2。
至此,我們回到頂部。 2是根,並被壓入堆棧。 2沒有左子節點,因此根變為空。 堆棧不為空。 2在堆棧的頂部。 它有一個正確的孩子,因此我們進入if語句的第二個分支。 這使3成為根。
我們回到外循環的頂部。 3是根,並被壓入堆棧。 3沒有左子節點,因此根變為空。 堆棧不為空。 3沒有合適的孩子,因此我們進入if語句的第一個分支。 我們打印出3。然后因為3是2的正確子級-2現在位於堆棧的頂部-我們將2彈出堆棧,打印出2,並且根變為空。
我們回到循環的頂部。 根已經為空,因此沒有任何內容被壓入堆棧。 堆棧不為空。 1在堆棧的頂部。 此時,正確的做法是從堆棧中彈出1,因為我們已經處理了它的正確子級; 但是,1在堆棧的頂部,並且確實有一個正確的子代,因此我們進入if語句的第二個分支,而2成為根。 這種情況與前兩段中的情況完全相同,其中1是堆棧上的唯一元素,而2是根,因此我們回到了無限循環。
如果我們更改示例,使3也有一個名為4的正確子元素,那么,如果我沒看錯,我們將永遠不會打印出2並循環打印出4和3。
要解決此問題,只要要處理的元素是堆棧頂部的右子元素,就應該繼續彈出堆棧。 我尚未對此進行編譯或測試,但是我認為編寫類似
if (!top(s) -> right)
{
root = pop(s);
printf("%d ", root -> data);
while (!stack_isEmpty(s) && root == top(s) -> right)
{
root = pop(s);
printf("%d ", root -> data);
}
if (!stack_isEmpty(s) && root == top(s) -> left)
{
// checking root == top(s) -> left is probably redundant,
// since the code is structured so that root is either
// a child of top(s) or null if the stack is not empty
root = top(s) -> right;
}
else
{
root = NULL;
// could actually break out of outer loop here, but
// to be more consistent with code in the question
}
}
發布此答案以提供@Evan VanderZee建議的解決方案的完整代碼
void postorder_nonrec_2(treenode *root)
{
stack_t *s;
stack_init(&s, 100);
while(1)
{
while(root)
{
push(s, root);
root = root -> left;
}
if(stack_isEmpty(s))
break;
if (!top(s) -> right)
{
root = pop(s);
printf("%d ", root -> data);
while (!stack_isEmpty(s) && root == top(s) -> right)
{
root = pop(s);
printf("%d ", root -> data);
}
root = NULL;
}
else
{
root = top(s) -> right;
}
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.