输出是正确的,但每次打印输出后程序崩溃
Output is correct but program crashes after printing the output everytime
我在不使用递归的情况下实现预定的二叉树遍历。
这是我的代码:
#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 关键字,可以将您带回到该代码块的开头,这就是最后 while 的目的。这是你的循环中的一个循环,没有检查。
你的 preOrd()
函数被搞砸了。
1.Don不使用 goto
首先你有一个 goto
在循环的结尾,在循环的开头跳转。这会阻止 while
条件被验证并导致永远循环。一旦堆栈为空,它将尝试 pop
/top
这会导致 UB(这里是崩溃)!
每次想使用 goto
时,请三思!首选 break
中断循环,或 continue
正确循环。这将避免将来出现此类问题。
今日名言:“goto - 臭名昭著的 goto。” - Bjarne Stroustrup
2.Then修改循环逻辑
如果你只注释掉goto
,它会更好用,但在第二级之后停止(这次没有崩溃)。显然,您不会将所需的所有内容都压入堆栈。
这里是修改后的版本:
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);
}
}
我在不使用递归的情况下实现预定的二叉树遍历。 这是我的代码:
#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 关键字,可以将您带回到该代码块的开头,这就是最后 while 的目的。这是你的循环中的一个循环,没有检查。
你的 preOrd()
函数被搞砸了。
1.Don不使用 goto
首先你有一个 goto
在循环的结尾,在循环的开头跳转。这会阻止 while
条件被验证并导致永远循环。一旦堆栈为空,它将尝试 pop
/top
这会导致 UB(这里是崩溃)!
每次想使用 goto
时,请三思!首选 break
中断循环,或 continue
正确循环。这将避免将来出现此类问题。
今日名言:“goto - 臭名昭著的 goto。” - Bjarne Stroustrup
2.Then修改循环逻辑
如果你只注释掉goto
,它会更好用,但在第二级之后停止(这次没有崩溃)。显然,您不会将所需的所有内容都压入堆栈。
这里是修改后的版本:
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);
}
}