简单的二叉搜索树.分段错误

simple binary search tree. Segmentation Fault

本文关键字:分段 错误 搜索树 简单      更新时间:2023-10-16

只是一个简单的BST来按顺序打印数字。不知道我做错了什么。

#include <iostream>
using namespace std;
class bst {
 private:
  bst* root;
  bst* left;
  bst* right;
  int value;
 public:
  bst(const int& numb) : root(NULL), left(NULL), right(NULL) {
    value = numb;
  }
  void insert(const int& numb) {
    if (numb < value) {
      if (left == NULL) {
        left = new bst(numb);
        left->root = left;
      } else { 
        left->insert(numb);
      }
    } else if (numb > value) {
      if (right == NULL) {
        right = new bst(numb);
        right->root = right;
      } else {
       left->insert(numb);  
      }
    } else if (numb == value) {
      cout << "duplicated value" << endl;
    }
  }
  void inorder() {
    if (left == NULL) cout << value << endl;
    else left->inorder();
    right->inorder();
  }
};

int main() {
  bst tree(5);
  tree.insert(7);
  tree.insert(1);
  tree.insert(3);
  tree.insert(2);
  tree.insert(9);
  tree.insert(10);
  return 0;
}

29行应为:

 right->insert(numb);

当前为:

 left->insert(numb);

我强烈建议查看 gdb 来解决此类情况。

inorder()应该是:

if (left != NULL) left->inorder();
cout << value << endl;
if (right != NULL) right->inorder();

我认为其余的是正确的。

贯穿始终的逻辑错误。

崩溃在这里:

  if (right == NULL) { 
    right = new bst(numb); 
    right->root = right; 
  } else { 
   left->insert(numb);   
  } 

否则情况应使用右,而不是左。

至少在我看来,你的基本设计是有缺陷的。虽然我意识到许多教科书(等等)将树描述为递归结构,其中每个节点有两个子树,但我从未发现这是设计代码的好方法。

至少根据我的经验,在实际代码中,最好将树中节点的概念与整个树的概念分开。只有树应该对外界可见; node应该隐藏在树内,外界看不见。

class bst {
    class node {
        int value;
        node *left;
        node *right;
        // ...
    };
    // ...
    node *root;   
};

然后,我将insert分成两部分:一个接受值的公共函数,然后以root为起点转发到第二个函数。第二个实际上遍历这三个项目并插入新项目:

// public interface:
void insert(int v) {    
    insert(new node(v), root);
}
// private workhorse:
void insert(node *n, node *&pos) {
    if (pos == NULL)
        pos = n;
    else if (n->value < pos->value)
        insert(n,pos->left);
    else if (n->value > pos->value)
        insert(n,pos->right);
            else
                // duplicate value.
}

同样,inorder被拆分为公共和私有对,公共接口仅提供一个接口,而私有接口执行所有实际工作:

// public interface:
void inorder() {
    inorder(root);
}
// private worker
void inorder(node *n) {
    if (n==NULL)
        return;
    inorder(n->left);
    std::cout << n->value << endl;
    inorder(n->right);
}

对于它的价值:是的,我已经测试了这段代码,它至少可以与您在main中使用的输入一起使用。不过,它确实有缺点。例如,insertinorder 都递归遍历树,因此大而严重不平衡的树可能会导致堆栈溢出。迭代插入相当容易,但对于实际使用,您通常只需切换到某种平衡树。