[英]Inorder traversal of binary tree gives garbage value and segmentation fault after traversal
我正在嘗試使用堆棧遍歷二叉樹,遍歷成功,但最后的程序顯示垃圾值和分段錯誤錯誤。 我認為它不會一次又一次地達到頂峰,但我無法解決這個問題。
struct Node
{
int data;
Node *left;
Node *right;
Node(int x)
{
data = x;
left = NULL;
right = NULL;
}
};
Node *STACK[10] = { NULL };
int TOP = -1;
void push(Node *ptr)
{
if(TOP < 10) {
STACK[++TOP] = ptr;
}
}
void stackTraversal(Node *root)
{
Node *ptr = root; bool flag = false;
top:
while(ptr != NULL)
{
push(ptr);
ptr = ptr->left;
}
ptr = STACK[TOP];
TOP--;
while(ptr != NULL)
{
cout << ptr->data << " ";
if(ptr->right != NULL)
{
ptr = ptr->right;
flag = true;
break;
}
ptr = STACK[TOP];
TOP--;
}
if(flag)
goto top;
cout << "\nTHE END\n";
}
int main(int argc, char const *argv[])
{
Node *R = new Node(2);
Node *a = new Node(0);
Node *b = new Node(1);
Node *c = new Node(4);
Node *d = new Node(5);
Node *e = new Node(3);
R->right = c;
R->left = a;
a->right = b;
c->right = d;
c->left = e;
stackTraversal(R);
cout << endl;
return 0;
}
它給出了以下輸出。
Output:- 0 1 2 3 4 5 -786491 分段錯誤(核心轉儲)
從您的 output 可以看出,您已經遍歷了所有元素,最后訪問的元素是d
。
現在你在這個塊中,其中ptr
指向d
:
if(ptr->right != NULL)
{
ptr = ptr->right;
flag = true;
break;
}
ptr = STACK[TOP];
好的, d
沒有孩子,你不進入if
塊,你計划訪問的下一個節點是... STACK[-1]
。
修改你的算法。 我建議避免使用goto
,只要這是一種非常糟糕的做法。
假設總會有一些東西,您的算法會從堆棧中彈出。 但是 ptr 應該如何變成 NULL 來結束第二個循環呢?
結果,您的堆棧計數器變為負數,導致 UB(幸運的是)將自身表示為運行時錯誤。
你努力寫了一個push()
。 付出額外的努力編寫一個pop()
。 確保您的算法檢查空堆棧,或者如果堆棧為空,則pop()
返回nullptr
:
Node* pop()
{
if (TOP>=0) {
return STACK[TOP--];
}
else {
return nullptr;
}
}
當然,將以下序列替換為ptr = pop();
:
ptr = STACK[TOP];
TOP--;
除了在goto
之后使用 ptr 之外,所有pop()
后面都是正在檢查 null 的指針。 所以你需要添加一個額外的條件來避免這種情況:
if(flag && ptr)
goto top;
然后,當您運行該程序時,它將顯示項目,但您會看到下溢結束了該過程。
我們在 21 世紀: goto
不再是致命的, 如果可能的話,最好在 C++ 中避免。
外部循環可以優雅地替換 goto。 然后,您也可以擺脫標志:
void stackTraversal(Node *root)
{
...
while(ptr) // outer loop: no more goto
{
while(ptr) { // push the full left
push(ptr);
ptr = ptr->left;
}
ptr = pop(); // pop top node
while(ptr)
{
cout << ptr->data << " ";
cout.flush(); // in case of weird things happening afterwards
if(ptr->right) { // explore its right branch
ptr = ptr->right;
break; // this goes back to outer loop
}
else ptr = pop();
}
}
cout << "\nTHE END\n";
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.