二叉树的有序遍历给出遍历后的垃圾值和分段错误

我正在尝试使用堆栈遍历二叉树,遍历成功,但最后的程序显示了垃圾值和分段错误。我认为它不会一次又一次地到达顶部,但我无法解决此问题。

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;
}

正在给出以下输出。

输出:- 0 1 2 3 4 5 -786491分段错误(核心已转储)

dabengua5527 回答:二叉树的有序遍历给出遍历后的垃圾值和分段错误

从输出中可以看到,您遍历了所有元素,最后访问的元素是d

现在您在此块中,ptr指向d

        if(ptr->right != NULL)
        {
            ptr = ptr->right;
            flag = true;
            break;
        }
        ptr = STACK[TOP];

好吧,d没有孩子,您无需输入if块,而您打算访问的下一个节点是... STACK[-1]

修改您的算法。我建议避免使用goto,只要这是众所周知的坏习惯。

,

假设总是存在某些东西,您的算法将从堆栈中弹出。但是ptr然后应该如何变为NULL以结束第二个循环?

结果,您的堆栈计数器进入了导致UB的负数,UB幸运地将自身表示为运行时错误。

改进1:发现结局

您已努力编写push()。尽力编写pop()。如果堆栈为空,请确保算法checks for an empty stackpop()返回nullptr

Node* pop()
{
    if (TOP>=0) { 
        return STACK[TOP--];
    }
    else {
        return nullptr;
    }
} 

当然,请用ptr = pop();替换以下顺序:

ptr = STACK[TOP];
TOP--;

所有pop()后面都将检查指针是否为空,除非在goto之后使用ptr。因此,您需要添加一个额外的条件来避免这种情况:

if(flag && ptr)
    goto top;

当您运行程序时,它将显示项目,但是您会看到下溢结束了该过程。

改进2:摆脱goto

我们正处于21世纪:goto不再是一个死亡,而should better be avoided in C++ if possible

外部循环可以优雅地替换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"; 
}

Online demo

本文链接:https://www.f2er.com/3128409.html

大家都在问