使用 std::unique_ptr 的霍夫曼树代码不起作用

Code for Huffman tree using std::unique_ptr not working

本文关键字:霍夫曼 代码 不起作用 ptr std unique 使用      更新时间:2023-10-16

我正在为家庭作业构建一个霍夫曼编码器,我需要知道为什么我的代码不起作用。我已经在其他地方询问了早期版本,并得到了使用 std::unique_ptr 的提示,这样我的指针引用的节点在从矢量中删除时不会从内存中删除。

这是我到目前为止所拥有的:

#include <iostream>     // Allows the use of std::cout >> and std::cin <<.
#include <string>       // Allows the use of getline().
#include <fstream>      // Allows the use of file I/O.
#include <utility>      // Allows the use of std::bitset.
#include <vector>       // Allows the use of vectors.
#include <algorithm>    // Allows the use of std::sort().
#include <memory>       // Allows the use of std::unique_ptr.
struct node
{
    char data;
    int frequency;
    std::bitset<1> code;
    node *left;
    node *right;
    bool operator<(const node &temp) const {return frequency < temp.frequency;}
};
std::vector<node> nodeVector;
void getHuffmanData()
{
    std::ifstream inStream;
    int size;
    int tempFrequency;
    char tempData;
    node tempNode;
    inStream.open("huff-source.txt");
    if (inStream.fail())
    {
        std::cout << "Failure opening input file.n";
        exit(1);
    }
    inStream >> size;
    while (inStream.peek() != EOF)
    {
        inStream >> tempData;
        inStream >> tempFrequency;
        tempNode.data = tempData;
        tempNode.frequency = tempFrequency;
        nodeVector.push_back(tempNode);
    }
    inStream.close();
}
node buildHuffmanTree()     // Returns the root node, which points to all other nodes.
{
    node tempNode;
    node *x, *y;
    std::unique_ptr<node> a (new node);
    std::unique_ptr<node> b (new node);
    while (!nodeVector.empty())
    {
        std::sort(nodeVector.begin(), nodeVector.end());
        *a = nodeVector.front();
        x = a.release();
        tempNode.left = x;
        nodeVector.erase(nodeVector.begin());
        *b = nodeVector.front();
        y = b.release();
        tempNode.right = y;
        nodeVector.erase(nodeVector.begin());
        tempNode.frequency = x->frequency + y->frequency;
        nodeVector.push_back(tempNode);
        std::sort(nodeVector.begin(), nodeVector.end());
        if (nodeVector.size() == 1) {break;}
    }
    return tempNode;
}

int main()
{
    node test;
    getHuffmanData();
    test = buildHuffmanTree();
    std::cout << "Press 'Enter' to continue...";
    std::cin.get();
    return 0;
}

我的示例输入文件如下:

4
a 119
b 20
c 44
d 127

现在,我在 Xcode 中收到的错误消息发生在它通过 buildHuffmanTree() 运行一次后。它在包含"*a = nodeVector.front();"的行上写着"线程 1:EXC_BAD_ACCESS(code=1,地址=0x0)"。我将如何纠正循环,以便函数可以返回正确的树,如下所示:

   310
  /   
127   183
 d   /   
    64   119
   /     a
  20   44
   b    c

您正在尝试写入取消引用的空指针。让我逐步浏览您的代码以向您展示错误。

node buildHuffmanTree()     // Returns the root node, which points to all other nodes.
{
    node tempNode;
    node *x, *y;
    std::unique_ptr<node> a (new node); // a now points to a node in the heap
    std::unique_ptr<node> b (new node); // b now points to a node in the heap
    while (!nodeVector.empty())
    {
        std::sort(nodeVector.begin(), nodeVector.end());
        *a = nodeVector.front(); // you copy the first node in the vector into the node
                                 // on the heap pointed to by a
        x = a.release();         // x now points to the node on the heap pointed to by a
                                 // a now holds a nullptr and will not delete the node on the heap
        tempNode.left = x;       // tempNode.left now points to the node on the heap
        nodeVector.erase(nodeVector.begin());
        . . .
        tempNode.frequency = x->frequency + y->frequency;
        nodeVector.push_back(tempNode);
        std::sort(nodeVector.begin(), nodeVector.end());
        if (nodeVector.size() == 1) {break;}
    }
    return tempNode;
}

现在我们再次经历 while 循环

    while (!nodeVector.empty())
    {
        std::sort(nodeVector.begin(), nodeVector.end());
        *a = nodeVector.front(); // a now holds a nullptr, so this is BAD
        . . .
    }

我相信你没有完全理解std::unique_ptr的使用.您可能希望所有node对象的 std::unique_ptr 集合在整个程序中持久化,以便您拥有一组不会消失的唯一节点。若要将这些节点链接到树中,请使用常规指针(或共享指针)。当包含指针的对象/代码块时,应使用唯一指针全权负责删除指针指向的已分配内存。