【问题标题】:Segmentation Fault while searching a node in BST在 BST 中搜索节点时出现分段错误
【发布时间】:2020-11-06 20:55:22
【问题描述】:

我在二叉搜索树中编写了一个搜索功能。虽然该功能正常工作并且当键存在于树中时执行它应该执行的操作,但当它不存在时会给出分段错误。打印“是”或“否”是否正确,或者该函数是否应该返回指向节点的指针?

template<class T>
class Node{
public:
    T m_data;  
    Node<T>* m_left;
    Node<T>* m_right;

    Node(T data){
         m_data=data;
         m_left=nullptr;
         m_right=nullptr;
     }
};

template<class T>
class bst {
private:
    Node<T>* root;

public:
    bst() { root = nullptr; }
    ~bst() { deltree(root); }
    void addnode(Node<T>* node, T data) {
        
        if(this->root == nullptr) {
            Node<T>* new_node= new Node<T>(data);
            this->root = new_node;
        } else if(data > node->m_data) {
            if(node->m_right != nullptr) {
                addnode(node->m_right, data);
            } else {
                Node<T>* new_node = new Node<T>(data);
                node->m_right = new_node;
            }
        } else if(data < node->m_data) {
            if(node->m_left != nullptr) {
                addnode(node->m_left, data);
            } else {
                Node<T>* new_node = new Node<T>(data);
                node->m_left = new_node;
            }
        }
    }
    void addnode(T data) { addnode(this->root, data); }

    void searchkey(T data) { searchkey(data, this->root); }

    void searchkey(T data, Node<T>* node) {
        if(this->root == nullptr) {
            std::cout << "Empty :) ";
        }
        if(data == node->m_data) {
            std::cout << "Found";
        } else if(node->m_data > data) {
            searchkey(data, node->m_left);
        } else if(node->m_data < data) {
            searchkey(data, node->m_right);
        }

        else {
            std::cout << "NOt fOUND";
        }
    }

void deltree(Node<T>* node) {
        if(node) {
            deltree(node->m_left);
            deltree(node->m_right);
            delete node;
        }
};

【问题讨论】:

  • 无关:我真的希望在 bst 类中看到析构函数。
  • 请注意,您在void addnode(Node&lt;T&gt;* node, T data); 中存在严重问题 - 您递归地创建新的Nodes。您应该仅在找到数据槽时创建它,否则您会创建大量泄漏的Nodes。你还需要一个析构函数。 example
  • 好的,我会处理的。感谢您指出! @TedLyngmo
  • @TedLyngmo 我已经尝试解决这两个问题。

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


【解决方案1】:

您没有检查node 是否为null,因此正在尝试访问可能为空节点上的成员(m_datam_leftm_right)。只需添加一张支票即可。

使用这个:

void searchkey(T data) {
  if (this->root == nullptr) {             // <-- check if root is null in this function not
    std::cout << "Empty :) " << std::endl; //     the other one to reduce number of comparisons
  } else {
    searchkey(data, this->root);
  }
}

void searchkey(T data, Node<T> *node) {
  if (node == nullptr) {                   // <-- check if node is null
    std::cout << "Not found" << std::endl;
  } else if (node->m_data > data) {
    searchkey(data, node->m_left);
  } else if (node->m_data < data) {
    searchkey(data, node->m_right);
  } else {
    std::cout << "Found" << std::endl;
  }
}


更新:

最好从这样的函数返回一个指向节点的指针。如果您只是检查,那么您可以随时通过直接将结果与nullptr 进行比较来进行检查。总体而言,您可以选择如何实现它,以及您是否打算获得指向节点的指针。

更新 - 2:

Ted Lyngmo 的即兴代码:(修复了addnode 中的内存泄漏,简化了代码并添加了析构函数)

#include <iostream>

template<class T>
class bst {
private:
    struct Node {
        T m_data;
        Node* m_left = nullptr;
        Node* m_right = nullptr;

        Node(T data) : m_data(data) {}
    };

    Node* root = nullptr;

    void addnode(Node*& node, T data) {
        if(node == nullptr) {
            node = new Node(data);
        } else if(data > node->m_data) {
            addnode(node->m_right, data);
        } else if(data < node->m_data) {
            addnode(node->m_left, data);
        } else {
            std::cout << "Already Exists\n";
        }
    }

    void searchkey(T data, Node* node) {
        if(node == nullptr) {
            std::cout << "Not Found\n";
        } else if(data < node->m_data) {
            searchkey(data, node->m_left);
        } else if(node->m_data < data) {
            searchkey(data, node->m_right);
        } else {
            std::cout << "Found\n";
        }
    }

    void deltree(Node* node) {
        if(node) {
            deltree(node->m_left);
            deltree(node->m_right);
            delete node;
        }
    }

public:
    ~bst() { deltree(root); }

    void addnode(T data) { addnode(root, data); }
    void searchkey(T data) { searchkey(data, root); }
};

int main() {
    bst<int> b;
    b.addnode(10);
    b.addnode(12);
    b.addnode(11);
    b.searchkey(11);
}

【讨论】:

  • 只是一个查询!当指针到达叶节点时,它如何知道“node==nullptr”? 12 / \ 10 14 / \ / \ 8 11 13 15 如果我试图找到一个键为 112 的节点怎么办?它怎么知道“未找到”。
  • @TedLyngmo 我的错。不工作。 :/ stackoverflow.com/a/9286551/11613622
  • @Tushar 不是叶节点上的nullptr。但是,当您在叶节点上时,m_leftm_right 将为 null,您将在递归调用中将其传递给函数。
猜你喜欢
  • 1970-01-01
  • 2019-03-03
  • 1970-01-01
  • 2020-09-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-01-20
相关资源
最近更新 更多