簡體   English   中英

在C ++中的二進制搜索樹中搜索元素時遇到分段錯誤

[英]getting segmentation fault in searching an element in binary search tree in c++

node ** BST :: searchElement(node **tree, int item)
{
    if( ((*tree)->data == item) || ( (*tree) == NULL) )
        return tree;
    else if( item < (*tree)->data)
        return searchElement( &(*tree)->left, item);
    else
       return searchElement( &(*tree)->right, item);
}

int main(){
    BST obj;
    int choice;
    int height=0,total=0,n,item;
    node **tmp;
    system("cls");

    while(1){
        //clrscr();
        cout<<"*****BINARY SEARCH TREE OPERATIONS*****\n\n";
        cout<<"1) Create Tree\n";
        cout<<"2) Traversal\n";
        cout<<"3)  Insert Node\n";
        cout<<"4)  Search Node\n";
        cout<<"5 Find Smallest Node\n";
        cout<<"6) Find Largest Node\n";
        cout<<"7) Exit\n";
        cout<<"Enter your choice : ";
        cin>>choice;
        switch(choice){
            case 1 : //Create Tree
                cout<<"\n\n--Creating Tree--";
                cout<<"\nHow many nodes u want to enter : ";
                cin>>n;
                for(int i=0;i<n;i++){
                    cout<<"Enter value : ";
                    cin>>item;
                    obj.createTree(&obj.tree,item);
                }
                break;

            case 2 : //All Traversals
                cout<<"\n\nInorder Traversal : ";
                obj.inOrder(obj.tree);

                cout<<"\n\nPre-order Traversal : ";
                obj.preOrder(obj.tree);

                cout<<"\n\nPost-order Traversal : ";
                obj.postOrder(obj.tree);
                getch();
                break;

            case 3 : //Inserting a node in a tree
                cout<<"\n\n--Inserting Node in a tree--\n";
                cout<<"Enter value : ";
                cin>>item;
                obj.createTree(&obj.tree,item);
                cout<<"\nItem is inserted\n";
                getch();
                break;

            case 4 : //Search element
                cout<<"\n\n--Search Element--\n";
                cout<<"Enter item to searched : ";
                cin>>item;
                &(*tmp) = obj.searchElement(&obj.tree,item);
                if( (*tmp) == NULL)
                cout<<"\nSearch Element was not Found";
                else
                    cout<<"\nSearch Element was Found";
                getch();
                break;
            case 5 : //Find Smallest Node
                cout<<"\n\nSmallest Node is :  ";
                obj.findSmallestNode(obj.tree);
                getch();
                break;

            case 6 : //Find Largest Node
                cout<<"\n\nLargest Node is :  ";
                obj.findLargestNode(obj.tree);
                getch();
                break;



            case 7: exit(1);
        }//end of switch
    }
}

在上面的程序中,當我嘗試在樹中查找特定元素時,只有情況4無法正常工作。 我已經在主程序頂部包括了搜索元素成員函數。 當我調試程序時,我在搜索元素成員函數中遇到分段錯誤,尤其是在if條件下。 我真的不知道該怎么辦才能解決這個問題。 誰能幫我找出搜索元素成員函數內部發生分段錯誤的原因。 如果您對此程序有任何疑問,請告訴我。

if( ((*tree)->data == item) || ( (*tree) == NULL) )

應該

if ( ( (*tree) == NULL) || ((*tree)->data == item) )

如果*tree實際上 null,則在第一次檢查時將引用空指針。 交換它們將確保檢查(*tree)->data*tree不為NULL-由於短路評估

另外, &(*tmp)應該寫成tmp

您正在取消引用未初始化的指針(tmp)。 您應該為此分配內存,或者只是跳過它的使用(我真的不知道為什么在這里需要一個臨時的NODE **。)

這里有一些批評:
由於您僅搜索節點,因此不需要指針到指針。 唯一需要指針的指針是在實際需要修改參數時。 另外,由於您使用的是C ++,因此應該傳遞引用:node *&tree,而不是傳遞pp。 這樣一來,您就可以使用tree變量而不必取消引用它,因為編譯器會為您處理。

在if語句中,您不會檢查左指針或右指針是否為空指針。 我不確定是否為此使用了哨兵節點,但是我假設您沒有。 這樣,我將您的方法更改為:

node * BST :: searchElement(node *tree, int item)
{
    if(tree->data == item)
        return tree;
    //short circuit if statements
    else if( (tree->left != NULL) && (item < tree->data) )
        return searchElement( tree->left, item );
    else if( (tree->right != NULL) && (item > tree->data) ) //>= for duplicates
        return searchElement( tree->right, item );

    return NULL; //if it isn't found
}

是。 確實,正如Erik已經發布的那樣,您必須寫

if ( ( (*tree) == NULL) || ((*tree)->data == item) )

代替

if( ((*tree)->data == item) || ( (*tree) == NULL) )

因為如果item尚未在樹中,則在嘗試取消引用NULL指針時,您的代碼肯定會導致segfault。

還有另一個(不太明顯)的問題-絕對不必要的遞歸。 如果在插入或刪除樹節點時未進行仔細的平衡,則樹的高度最多為線性,因此遞歸深度最多為線性,這很容易導致堆棧溢出。 因此,您應該將searchElement函數轉換為

node** BST::searchElement( node** tree, int item )
{
    while(  ( (*tree) != NULL)  &&  ( (*tree)->data != item )  )
    {
        if( item < (*tree)->data )
        {
            tree = &(*tree)->left;
        }
        else
        {
            tree = &(*tree)->right;
        }
    }

    return tree;
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM