CPP:How 获取向量中的 REAL 元素?

CPP:How to get the REAL element in a vector?

我是 C++ 的新手,我正在制作一个用 C++ 编写的霍夫曼树,但我在生成树结构时遇到了麻烦。 这是我的代码:

    void Huffman::generateTree() {
        std::vector<Node> nodes;
        for (auto itr : freq) {
            nodes.push_back(*(new Node(itr.first, itr.second)));
        }
        while (nodes.size() > 1) {
            Node::sort(&nodes);
            Node leftNode = nodes.back();
            nodes.pop_back();
            Node rightNode = nodes.back();
            nodes.pop_back();
            Node newAnode = *new Node();
            newAnode.merge(&leftNode,&rightNode);
            nodes.push_back(newAnode);
        }
        root = &nodes.back();
        displayTree();
    }

终于合并到一个节点了,但是左节点和右节点是错误的: (出于调试目的,每个节点在创建时都有一个随机 ID,所以我发现了问题。)

NODE freq26|id96
|-Left:
   NODE freq10|id17
   |-Left:
   |--ERROR:SELF freq10|id17
   |-Right:
      NODE freq16|id19
      |-Left:
         NODE freq10|id17
         |-Left:
         |--ERROR:SELF freq10|id17
         |-Right:
            NODE freq16|id19
            |-Left:
               NODE freq10|id17
               |-Left:
               |--ERROR:SELF freq10|id17
               |-Right:
                  NODE freq16|id19
...endless loop

和输出一样,从第一个子节点开始,每个节点的左子节点是自己,右子节点是另一个节点,但只有两个相互切换,最后循环。

我搜索并阅读了一些关于此的 post 我知道这可能是由 pop_backpush_back 元素引起的 vector,指针可能指向另一个元素,但是如何我能解决吗?有没有办法得到vector中不受操作vector影响的REAL元素?

这是我的节点的一些代码:

//header
    class Node {
    private:
        char value;
        int frequency;
        Node *left;
        Node *right;
        String code;
...
    class Huffman{
    private:
        Node * root;
        std::map<char,int> freq;// calculated frequency of data
        bool generated;
//source
    bool Node::sortMethod::operator()(const Node &nodeA, const Node &nodeB) {
        return nodeA.getFrequency() > nodeB.getFrequency();//getFrequency(): simply return node's frequency int
    }
    void Node::sort(std::vector<Node> *nodes) {
        std::sort(nodes->begin(), nodes->end(), sortMethod());
    }
    Node *Node::merge(Node *pLeft, Node *pRight) {
        left = pLeft;
        right = pRight;
        frequency = left->getFrequency() + right->getFrequency();
        return this;
    }

欢迎提供有用的信息,谢谢!

正如评论所暗示的那样,您需要停止认为 C++ 类似于 Java,事实并非如此。

C++ 中的对象具有明确的生命周期,并且该语言不会阻止您在对象不复存在后保留对对象的引用或指针。

如果您希望某个东西的寿命超过创建它的调用,则需要动态分配它,并且应该跟踪它的生命周期。默认是std::unique_ptr,当指针被销​​毁时,它会删除它指向的内容。您可以通过 移动 unique_ptr.

来转让所有权

不幸的是,您无法使用 std::unique_ptrstd::priority_queue,因为您无法移动 top,而 pop 不会 return 值。否则我会建议使用它而不是重新实现它。

我认为您不必在每个循环中对节点进行排序,因为合并后的节点总是最大的 frequency,所以它们排在后面。

class Node;
// Aliases for types we will use
using NodePtr = std::unique_ptr<Node>;
using Nodes = std::vector<NodePtr>;

class Node {
private:
    char value;
    int frequency;
    NodePtr left;
    NodePtr right;
    std::string code;

    Node(char value, int frequency) : value(value), frequency(frequency) /*, code?*/{}
    Node(NodePtr left, NodePtr right) : /*value? ,*/ frequency(left->frequency + right->frequency), left(std::move(left)), right(std::move(right)) /*, code?*/{}
... 
};

// N.b. not members of Node
bool compareNodePtrs(const NodePtr & left, const NodePtr & right) {
    return left->getFrequency() > right->getFrequency();
}

void sortNodes(Nodes & nodes) {
    std::sort(nodes.begin(), nodes.end(), compareNodePtrs);
}

void Huffman::generateTree() {
    Nodes nodes;
    for (auto itr : freq) {
        nodes.emplace_back(std::make_unique<Node>(itr.first, itr.second));
    }
    sortNodes(nodes);
    while (nodes.size() > 1) {
        auto left = std::move(nodes.back());
        nodes.pop_back();
        auto right = std::move(nodes.back());
        nodes.pop_back();            
        nodes.emplace_back(std::move(left), std::move(right));
    }
    root = std::move(nodes.back());
    displayTree();
}