簡體   English   中英

二叉樹的中序遍歷遍歷后給出垃圾值和分段錯誤

[英]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(幸運的是)將自身表示為運行時錯誤。

改進1:檢測結束

你努力寫了一個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;

然后,當您運行該程序時,它將顯示項目,但您會看到下溢結束了該過程。

改進2:擺脫goto

我們在 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM