【问题标题】:Output is correct but program crashes after printing the output everytime输出正确,但每次打印输出后程序崩溃
【发布时间】:2016-04-23 12:52:31
【问题描述】:

我正在实现预先排序的二叉树遍历而不使用递归。 这是我的代码:

#include<iostream>
#include<stack>
using namespace std;

struct node{

int data;
node *left;
node *right;

};

node *getNewNode(int data){   //method for creating new node

node *newNode = new node();
newNode->data=data;
newNode->left=newNode->right = NULL;
return newNode;

}

node *Insert(node *root , int data){     //Method for insert new data in tree

if(root == NULL){
    root = getNewNode(data);
}
else if(data>root->data){
    root->right = Insert(root->right,data);
}
else{
    root->left = Insert(root->left,data);
}

return root;

}

void Print(node *root){  //Method for preorder traversal with recursion

if(root == NULL){
    return;
}

 cout<<root->data<<" ";
Print(root->left);

Print(root->right);

}

void preOdr(node *root){  //Without recursion

stack<node*> stk;
cout<<root->data<<" ";

do{
    a:
    if(!(root->right==NULL&&root->left==NULL)){
        if(root->right!=NULL){
             stk.push(root->right);
        }
        if(root->left!=NULL){
             stk.push(root->left);
        }
    }
    cout<<stk.top()->data<<" ";
    root=stk.top();
    stk.pop();
    goto a;
}
while(!stk.empty());



}

int main(){

node *root = NULL;
root = Insert(root,10);
root = Insert(root,6);
root = Insert(root,15);
root = Insert(root,3);
root = Insert(root,9);
root = Insert(root,11);
root = Insert(root,17);
root = Insert(root,11);
root = Insert(root,62);
root = Insert(root,135);
root = Insert(root,30);
root = Insert(root,98);
root = Insert(root,117);
root = Insert(root,176);

Print(root);
cout<<endl;
preOdr(root);

return 0;
}

在我的程序中,我还创建了使用递归的前序遍历方法来验证非递归方法给出的输出,即Print()

在非递归方法中,首先我打印根,然后将该节点的左右子节点(如果有)分别推入堆栈。在此之后,我从堆栈中弹出项目并重复上述过程,直到堆栈不为空。

当我运行此代码时,它会正确输出,但之后会崩溃。我不明白名为preOrd() 的方法有什么问题。我附上了完整的代码以便更好地理解。

【问题讨论】:

  • 去掉 goto 中的 preOdr 它没有任何作用,你最终会在你的 do {} while() 中创建一个无限循环

标签: c++ data-structures tree binary-search-tree tree-traversal


【解决方案1】:

你的preOrd() 函数搞砸了。

1.不要使用goto

首先你在循环的末尾有一个goto,在循环的开头直接跳转。这可以防止while 条件被验证并永远导致循环。一旦堆栈为空,它将尝试pop/top 导致UB(这里是崩溃)!

每当您想使用goto 时,请三思而后行!首选break 中断循环,或continue 正确循环。这样可以避免将来出现此类问题。

每日报价:“goto - 臭名昭著的 goto。” - Bjarne Stroustrup

2.然后修改循环逻辑

如果只是注释掉goto,效果会更好,但是在第二级之后就停止了(这次没有crash)。显然,您不会将所有需要的东西都压入堆栈。

这里是修订版:

void preOdr(node *root){  //Without recursion

    stack<node*> stk;
    stk.push(root);           // put the root not on th stack and 
                              // then process it like the others
    while (!stk.empty()) {
        root=stk.top();
        stk.pop();
        cout<<root->data<<" ";  // get and show top of stack
        if(root->right)         // then push the childern 
            stk.push(root->right);
        if(root->left)    
            stk.push(root->left);
    }
}

Live demo

【讨论】:

    【解决方案2】:

    您有一个 goto 关键字,可将您带回到该代码块的开头,这就是结尾的 while 的目的。这是你的循环中没有检查的循环。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2010-09-26
      • 1970-01-01
      • 2018-09-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多