【问题标题】:Inorder traversal of binary tree gives garbage value and segmentation fault after traversal二叉树的中序遍历给出了遍历后的垃圾值和分段错误
【发布时间】:2020-03-06 12:27:36
【问题描述】:

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

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 分段错误(核心转储)

【问题讨论】:

    标签: c++ segmentation-fault stack binary-tree garbage


    【解决方案1】:

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

    现在你在这个块中,ptr 指向d

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

    好的,d 没有孩子,你不进入if 块,你计划访问的下一个节点是...STACK[-1]

    修改你的算法。我建议避免使用goto,只要这是一种非常糟糕的做法。

    【讨论】:

      【解决方案2】:

      假设总会有一些东西,你的算法会从堆栈中弹出。但是 ptr 应该如何变为 NULL 来结束第二个循环?

      因此,您的堆栈计数器变为负数,导致 UB(幸运的是)将自身表示为运行时错误。

      改进一:检测结束

      您努力写了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--;
      

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

      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

      【讨论】:

        猜你喜欢
        • 2019-07-24
        • 1970-01-01
        • 1970-01-01
        • 2018-09-19
        • 1970-01-01
        • 2012-01-01
        • 2022-11-11
        • 2012-11-09
        相关资源
        最近更新 更多