【问题标题】:Are C++ pointers allocated same address every time they are newly allocated?每次新分配的 C++ 指针是否都分配了相同的地址?
【发布时间】:2021-04-04 09:50:39
【问题描述】:

我是 C++ 新手,我正在尝试在其中实现 Huffman 代码。为此,我必须在其中实现一个树状结构,这需要我在结构中实现指针。但是我面临的问题是,每次我为变量分配一个新值时,它都会获得相同的地址,而我试图实现的树在最顶层的元素处变得自引用,这阻止了我遍历它.

这是我的代码 -

#include<iostream>
#include<string.h>
#include<vector>
using namespace std;

struct node{
    int freq;
    string symbol;
    node *left = nullptr, *right=nullptr;
    string huff;
};

vector<node> nodes;

vector<node> nodeSort(vector<node> arr, int s){
    for(int x=0;x<s;x++){
        for(int y=x+1;y<s;y++){
            if(arr[x].freq>arr[y].freq){
                node temp = arr[x];
                arr[x] = arr[y];
                arr[y] = temp;
            }
        }
    }
    return arr;
}

void printHuff(node Node, string val=""){
    string newval = val+Node.huff;
    if(Node.left!=nullptr){
        printHuff(*Node.left,newval);
    }
    if(Node.right!=nullptr){
        cout<<2;
        printHuff(*Node.right,newval);
    }
    if(Node.left==nullptr and Node.right==nullptr){
        cout<<Node.symbol<<" -> "<<newval;
    }
}

int main(){
    char symbols[] = {'A','B','C','D'};
    int freq[] = {5,1,6,3};
    for(int x=0;x<4;x++){
        node temp;
        temp.freq = freq[x];
        temp.symbol = symbols[x];
        temp.huff = "";
        nodes.push_back(temp);
    }

    while(nodes.size()>1){
        nodes = nodeSort(nodes,nodes.size());
        node left = nodes[0];
        node right = nodes[1];
        node temp;
        left.huff += "0";
        right.huff += "1";
        temp.freq = left.freq + right.freq;
        temp.symbol = left.symbol + right.symbol;
        temp.left = &left;
        temp.right = &right;
        nodes.erase(nodes.begin());
        nodes.erase(nodes.begin());
        nodes.push_back(temp);
    }
    node a = nodes[0];
    cout<<a.left->symbol<<endl;
    cout<<a.right->symbol<<endl;
    cout<<a.right->left->symbol<<endl;
    cout<<a.right->right->symbol<<endl;
    // printHuff(nodes[0]);
    return 0;
} 

这是预期的霍夫曼树 -

这是输出 -

C
BDA
C
BDA

这绝对是错误的。但我无法找出我做错了什么参考?我是 C++ 新手,虽然我在 Python 中实现了相同的算法,但我无法理解这里出了什么问题。

【问题讨论】:

  • 当您向树中添加节点时,您可能每次都需要使用new(至少间接地)创建一个新节点。
  • temp.left = &amp;left; temp.right = &amp;right; -- leftright 是临时变量。每次while 循环迭代时,这些变量都会消失。因此,您正在存储临时人员的地址。未定义的行为。
  • 虽然我在 Python 中实现了相同的算法——C++ 不是 Python、Java、C# 或任何其他看起来像 C++ 的语言。 C++就是C++。要在 C++ 中正确编码特定的数据结构,您需要了解 C++,而不是使用其他语言作为编写代码的指南。 C++ 是基于值的,而不是基于引用的,这是让那些不了解 C++,但使用其他语言作为编写 C++ 代码的指南的程序员的主要障碍。
  • 您可能需要阅读以下链接以获取有关 C++ 对象生命周期的信息:en.cppreference.com/w/cpp/language/lifetime
  • @Deekshant -- Notre 我提到你正在存储临时变量的 address。由于变量是临时变量,当变量超出范围时,该地址指向什么?

标签: c++ algorithm stl huffman-code


【解决方案1】:

问题在于node.erase(),它正在删除您通过temp.lefttemp.right 指向的节点。更好的方法是形成node* 的向量,然后通过new 运算符形成节点并将指针存储在向量中。这样,当您执行node.erase() 时,它只会擦除指针而不是节点本身。代码如下:

#include<iostream>
#include<string.h>
#include<vector>
using namespace std;

struct node{
    int freq;
    string symbol;
    node *left = nullptr, *right=nullptr;
    string huff;
};

vector<node *> nodes;

vector<node*> nodeSort(vector<node*> arr, int s){
    for(int x=0;x<s;x++){
        for(int y=x+1;y<s;y++){
            if(arr[x]->freq>arr[y]->freq){
                node *temp = arr[x];
                arr[x] = arr[y];
                arr[y] = temp;
            }
        }
    }
    return arr;
}

void printHuff(node *Node, string val=""){
    
    if(Node->left!=NULL){
        printHuff(Node->left,val+"0");
    }
    if(Node->right!=NULL){
        // cout<<2;
        printHuff(Node->right,val+"1");
    }
    if(Node->left==NULL and Node->right==NULL){
        cout<<Node->symbol<<" -> "<<val<<endl;
    }
}

int main(){
    char symbols[] = {'A','B','C','D'};
    int freq[] = {5,1,6,3};
    for(int x=0;x<4;x++){
        node *temp = new node;
        temp->freq = freq[x];
        temp->symbol = symbols[x];
        temp->huff = "";
        nodes.push_back(temp);
    }

    for(auto it: nodes){
        cout<<it->symbol<<" "<<it->freq<<endl;
    }
    while(nodes.size()>1){
        nodes = nodeSort(nodes,nodes.size());
        node *left  = nodes[0];
        node *right = nodes[1];
        node *temp = new node;
        // left.huff += "0";
        // right.huff += "1";
        temp->freq = left->freq + right->freq;
        temp->symbol = left->symbol + right->symbol;
        temp->left = left;
        temp->right = right;
        nodes.erase(nodes.begin());
        nodes.erase(nodes.begin());
        nodes.push_back(temp);
    }
    // node a = nodes[0];
    // cout<<a.left->symbol<<endl;
    // cout<<a.right->symbol<<endl;
    // cout<<a.right->left->symbol<<endl;
    // cout<<a.right->right->symbol<<endl;
    printHuff(nodes[0]);
    return 0;
} 

也不要使用using namespace std。阅读this question,欢迎使用 C++。

【讨论】:

  • 答案似乎打印了正确的输出,但使用 new 运算符如何影响结果而不是我在做什么?
  • 实际上,new 运算符正在创建一个节点并返回指向该节点的指针,因此当您执行 nodes.erase() 时,它只是擦除指针而不是您使用 @ 创建的节点987654333@ 运算符,但在您的代码中,您正在获取节点向量,并且通过执行 nodes.erase() 您正在删除节点本身。
猜你喜欢
  • 2022-11-22
  • 2011-02-27
  • 2015-07-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-10-02
  • 1970-01-01
  • 2020-09-14
相关资源
最近更新 更多