分段故障(核心已转储)-线程二进制搜索树

时间:2019-01-31 02:30:15

标签: c++ binary-tree binary-search-tree

我一直收到以下错误:分段错误(核心已转储)。我发现了导致问题的代码行(在程序内部以注释标记)。请告诉我为什么会发生此错误,以及如何解决该错误。

我试图使我的代码(在纸上)空运行,但从我的理解来看,没有逻辑错误。
我只是最近才开始编码和stackoverflow,请引导我逐步解决问题以及代码。谢谢!

class tree
{
struct node    // Creates a node for a tree
{
    int data;
    bool rbit,lbit;  // rbit/lbit= defines if right/left child of root is present or not
    node *left,*right;
};
public:
    node *head,*root;
    tree() // constructor initializes root and head  
    {
        root=NULL;
        head=createnode(10000);
    }
    node *createnode(int value)  
    {// Allocates memory for a node then initializes node with given value and returns that node
        node *temp=new node ;
        temp->data=value;
        temp->lbit=0;
        temp->rbit=0;
        temp->left=NULL;
        temp->right=NULL;
        return temp;
    }
    void insert(node *temp,int value) // Creates binary search tree node by node
    {
        if(root==NULL)  // Checking if tree is empty
        {
            root=createnode(value);  //Root now points to new memory location 
            head->left=root;
            head->lbit=1;
            root->left=head;//this line gives the segmentation fault (what i thought before correction) 
        }   

    }
    void inorder(node *root) // Inorder traversal of tree (this function is logically incorrect) 
    {
        if(root==NULL)
            return;
        inorder(root->left);
        cout<<root->data<<"\t";
        inorder(root->right);
    }
    void getdata()//Accepts data , creates a node through insert() , displays result through inorder()
    {
        int data;
        cout<<"Enter data"<<endl;
        cin>>data;  
        insert(root,data);
        inorder(root);
    }
 /*void inorder(node *root) // Working inorder code
{
    if(root->lbit==1)
    inorder(root->left);
    cout<<root->data<<"\t";
    if(root->rbit==1)
    inorder(root->right);
}*/
};
int main()
{

    tree t; // Tree Object 
    t.getdata();  // Calling getdata
    return 0;
}

3 个答案:

答案 0 :(得分:3)

我认为评论部分主要反映了误解。很容易相信您在特定行上 ON 遇到了崩溃。

实际上并非如此。取而代之的是,您在树中创建了一个循环,该循环导致inorder函数导致无限递归。这会导致堆栈溢出并导致段错误-如果您只是在连接了调试器(例如gdb)的情况下运行程序,这将非常容易发现。

temp = createnode(value);
if(root == NULL)
{
    root = temp;
    head->left = root;
    head->lbit = 1;
    temp->left = head;
}   

看看刚才创建的循环:

head->left points to root
root->left == temp->left, which points to head

现在将遍历有序遍历:

root
  head
    root
      head
        root
          head
            ...

由于它永远不会到达左分支的末尾,因此该函数在溢出堆栈和崩溃之前永远不会输出任何内容。

因此,您的代码在逻辑上不正确。其中存在一个基本的设计缺陷。您需要重新考虑树中存储的内容以及原因。

答案 1 :(得分:1)

从代码中

    root=temp;  //Root now points to temp
    head->left=root;
    head->lbit=1;
    temp->left=head;// this line gives the segmentation fault 

根未指向temp。 temp(pointer)被分配给root(pointer)。 head的左指针是root,而temp的左指针是head(这意味着root的左指针是head)。因此在函数“顺序”中,

    void inorder(node *root) // Inorder traversal of tree
    {
        if(root==NULL)             <<<<<<
            return;
        inorder(root->left);
        cout<<root->data<<"\t";
        inorder(root->right);
    }

参数节点* root(左)从不为NULL,函数从不返回。

答案 2 :(得分:0)

没有确切的信息(例如node.lbit)。

问题的insert()函数将不起作用。它传递的值会立即被覆盖(以及其他问题)。 tree.head的作用没有说明,因此将其忽略。字段node.lbitnode.rbit看起来是node.left != NULL的多余标志(与右边类似)。这些也被省略。 insert()也没有正确创建树。

void insert(int value) // Insert a value into the tree (at branch)
{
    // Create a new node to insert
    struct node *temp = createnode(value);

    if (root == NULL)  // Checking if tree is empty
    {
        root = temp;  //Root now points to temp
    }  
    else 
    {
        insertAtBranch(root, temp);
    }
}

// recursively find the leaf-node at which to insert the new node
void insertAtBranch(node *branch, node *new_node)
{
    // to create a BST, less-than go left
    if (new_node->value <= branch->value)
    {
        if (branch->left == NULL)
            branch->left = new_node;  // There's no left-branch, so it's the node
        else
            insertAtBranch(branch->left, new_node);  // go deeper to find insertion point
    }
    else // greater-than go right
    {
        if (branch->right == NULL)
            branch->right = new_node;
        else
            insertAtBranch(branch->right, new_node);
    }
}         

想象一下二叉树如何工作。新节点只能插入到边缘。因此,您查看一个给定的节点,并确定该新节点是否小于或小于您正在查看的节点(当然,除非树为空)。

假设new-node.value小于branch-node.value,您想向左分支。仍然具有相同的节点,如果它没有左分支(node.left == NULL),则新节点的左分支。否则,您需要沿着左分支行驶并再次检查。

我本可以将node设为一个类,并使用构造函数至少设置默认属性和value。但这没什么大不了的。