繁体   English   中英

删除时出现分段错误

[英]Segmentation fault when deleting

我对 C++ 还很陌生,我正在尝试实现树结构,但我遇到了在删除树时出现的分段错误。 这段代码非常简单,我有一个 class 节点,其中包含指向其子节点的指针。

#include <vector>

class Node
{
public:
    int data1, data2;
    std::vector<Node*> children;
    Node* add_child(double data1, double data2) 
    { 
        Node* n = new Node(data1, data2);
        children.push_back(n); 
        return n;
    }
    Node(double data1, double data2)
        :data1(data1), data2(data2)
    { }
    ~Node() 
    {
        for(auto child : children)
        {
            delete child;
        }
        children.clear();
    }
};
int main()
{
    Node root = Node(0, 0); 
        
    Node* n = &root;
    for(int i = 0; i < NB; ++i)
    {
        n = n->add_child(0, 0);
    }
}

主要创建一个非常简单的结构,但有错误就足够了。 段故障仅发生在 NB 的值大于 170 000 时。

基于非递归程序删除整个二叉树的例子,我们可以修改你的应用程序如下:

#include <iostream>

using namespace std;

#include <vector>
#include <queue>

class Node
{
public:
    Node* add_child(double data1, double data2) 
    { 
        Node* n = new Node(data1, data2, false);
        children.push_back(n); 
        return n;
    }
    
    Node(double data1, double data2, bool is_root = true )
        :data1(data1), data2(data2), is_root(is_root)
    {
    }
    
    ~Node() 
    { 
       if( is_root ) deleteTree();
    }
    
    size_t get_num_childs()
    {
        return children.size();
    }
    
    Node* get_child( size_t index )
    {
        return children[index];
    }
    
private:

    /* Non-recursive function to delete an entire tree. */
    void deleteTree() 
    { 
        // Create an empty queue for level order traversal 
        queue<Node *> deleteQueue; 
      
        // Do level order traversal starting from root 
        for( int index = 0; index < children.size(); index++ )
        {
            deleteQueue.push( children[index]);
        }
        
        while( !deleteQueue.empty()) 
        { 
            Node *node = deleteQueue.front(); 
            deleteQueue.pop();
            
            for( int index = 0; index < node->get_num_childs(); index++ )
            {
                // Add all childs to queue for deleting
                deleteQueue.push( node->get_child( index ));
            }
      
            delete node;
        } 
    }

private:
    int data1, data2;
    std::vector<Node*> children;
    bool is_root;
};

int main()
{
    Node root = Node(0, 0); 
        
    Node* n = &root;
    for(int i = 0; i < 17000; ++i)
    {
        n = n->add_child(0, 0);
    }
    
    return 0;
}

正如评论中提到的,递归调用节点析构函数会导致堆栈溢出,然后是分段错误。

所以为了解决这个问题,我们必须坚持非递归删除节点。 这是在deleteTree()方法的支持下完成的。 为此,我们在内部构建了一个包含所有需要删除的节点的队列。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM