C++ C++;图类指针混淆

C++ C++;图类指针混淆,c++,pointers,graph,C++,Pointers,Graph,我试图构建一个图形类,其中图形由邻接列表表示。图形本身是指针向量,其中每个指针指向节点的链接列表。无论出于何种原因,当我使用print graph函数时,程序都不会输出任何内容。谁能告诉我我做错了什么,也许我对指针的误解在哪里?提前谢谢 #include <array> #include <vector> #include <tuple> #include <unordered_map> class Node { public:

我试图构建一个图形类,其中图形由邻接列表表示。图形本身是指针向量,其中每个指针指向节点的链接列表。无论出于何种原因,当我使用print graph函数时,程序都不会输出任何内容。谁能告诉我我做错了什么,也许我对指针的误解在哪里?提前谢谢

#include <array>
#include <vector>
#include <tuple>
#include <unordered_map>

class Node
{
    public:

    int vertex;
    int value;
    Node* next;

    Node(int ver)
    {
        vertex = ver;
    };
};

class Graph
{
    public:

    int n_nodes;
    std::unordered_map<int,Node*> graph;
    
    Graph(int n)
    {   
        n_nodes = n;
        for(int i=0;i<n;i++)
        {
            graph.insert({i,nullptr});
        };
    };

    void add_edge(int src,int des,int val)
    {
        Node node_des = Node(des);
        node_des.value = val;
        node_des.next = graph[src];
        graph[src] = &node_des;

        Node node_src = Node(src);
        node_src.value = val;
        node_src.next = graph[des];
        graph[des] = &node_src;
    };

    void print_graph()
    {
        for(int i =0; i<n_nodes;i++)
        {
            std::string str = "Head "+std::to_string(i);
            Node node = *graph[i];
            while (&node != nullptr)
            {
                str=str+" -> "+std::to_string(node.vertex);
                node = *(node.next);
            };

            std::cout<<str<<std::endl;
        };
    };
};

int main()
{
    Graph g = Graph(6);
    g.add_edge(0,1,3);
    g.add_edge(2,1,4);
    g.add_edge(0,4,1);
    g.add_edge(4,5,6);
    g.add_edge(5,3,2);
    g.add_edge(4,3,3);
    g.add_edge(3,2,5);
    g.add_edge(4,1,1);
    g.add_edge(3,1,2);

    g.print_graph();
    return 0;
}```

#包括
#包括
#包括
#包括
类节点
{
公众:
int顶点;
int值;
节点*下一步;
节点(内部版本)
{
顶点=垂直;
};
};
类图
{
公众:
int n_节点;
std::无序映射图;
图(int n)
{   
n_节点=n;

对于(int i=0;i来说,由于@drescherjm,我做了这些更改。问题是我创建了一个局部变量并引用了它的地址,而不是显式地创建一个指针并将其设置为一个新的节点实例,在这个节点实例中,对象的生存期是动态控制的

#include <bits/stdc++.h> 
#include <array>
#include <vector>
#include <tuple>
#include <unordered_map>

class Node
{
    public:

    int vertex;
    int value;
    Node* next;

    Node(int ver)
    {
        vertex = ver;
    };
};

class Graph
{
    public:

    int n_nodes;
    std::unordered_map<int,Node*> graph;
    
    Graph(int n)
    {   
        n_nodes = n;
        for(int i=0;i<n;i++)
        {
            graph.insert({i,nullptr});
        };
    };

    void add_edge(int src,int des,int val)
    {
        Node * node_des = new Node(des);
        node_des->value = val;
        node_des->next = graph[src];
        graph[src] = node_des;

        Node * node_src = new Node(src);
        node_src->value = val;
        node_src->next = graph[des];
        graph[des] = node_src;
    };

    void print_graph()
    {
        for(int i =0; i<n_nodes;i++)
        {
            std::string str = "Head "+std::to_string(i);
            Node * node_ptr = graph[i];
            while (node_ptr != nullptr)
            {
                str=str+" -> "+std::to_string(node_ptr->vertex);
                node_ptr = node_ptr->next;
            };
            std::cout<<str<<std::endl;
        };
    };
};

int main()
{
    Graph g = Graph(6);
    g.add_edge(0,1,3);
    g.add_edge(2,1,4);
    g.add_edge(0,4,1);
    g.add_edge(4,5,6);
    g.add_edge(5,3,2);
    g.add_edge(4,3,3);
    g.add_edge(3,2,5);
    g.add_edge(4,1,1);
    g.add_edge(3,1,2);

    g.print_graph();
    return 0;
}
#包括
#包括
#包括
#包括
#包括
类节点
{
公众:
int顶点;
int值;
节点*下一步;
节点(内部版本)
{
顶点=垂直;
};
};
类图
{
公众:
int n_节点;
std::无序映射图;
图(int n)
{   
n_节点=n;
对于(int i=0;ivalue=val;
node_des->next=图形[src];
图[src]=节点;
Node*Node_src=新节点(src);
节点\u src->value=val;
node_src->next=graph[des];
图[des]=node_src;
};
void print_graph()
{
对于(int i=0;ivertex);
node_ptr=node_ptr->next;
};

std::cout如果可能的话,您可以只使用vector of vector而不是链表,并且根本不使用指针。因为内存缓存向量操作中的一些插入可能比链表更快,所以类似以下结构:

struct Node2 {
    int vertex; 
    int value;
};

struct Edge2 {
    int src, des, value;
};

struct Graph2 {
    int n_nodes;
    std::vector<std::vector<Node2>> graph; 

    void add_edge(Edge2 edge) {
        graph[edge.src].emplace_back(edge.des, edge.value);
        graph[edge.des].emplace_back(edge.src, edge.value);
    }

    void add_edge(std::initializer_list<Edge2> edges)
    {
        std::for_each(edges.begin(), edges.end(), [this](auto &e) { add_edge(e); });
    };
}
struct节点2{
int顶点;
int值;
};
结构边2{
int src,des,value;
};
结构图2{
int n_节点;
向量图;
无效添加_边(边2边){
图形[edge.src].emplace_back(edge.des,edge.value);
图形[edge.des].emplace_back(edge.src,edge.value);
}
void add_edge(std::initializer_list edges)
{
std::for_each(edges.begin()、edges.end()、[this](自动&e){add_edge(e);});
};
}
结束比链表更容易、更快


Node Node=*graph[i];
然后
当(&Node!=nullptr)
节点是一个局部变量(在堆栈上),它永远不能是nullptr。
graph[des]=&node_src;
一旦作用域结束,
node_src
就不再存在,并且您有一个悬空指针。您不能将局部变量的地址存储在存在时间比局部变量长的结构中。事实上,
(&(
任何
)!=nullptr)
始终为真。没有地址可能为空的表达式。我将更仔细地重新计算代码。最有可能用于此赋值的是使用Node*和
new
而不是Node和&someLocal变量。使用
new
可以创建指向内存的指针,在这里可以控制其持续时间,而不是局部变量t超出了范围。谢谢!链表实现将以更少的内存复杂性结束,对吗?顺便说一句,不,它仍然是O(n)在边的数量上。实际上,这取决于,但大多数情况下也不是。每个节点2的大小都比节点小,并且所有节点都连接在一个向量中,因此内存效率较低的唯一可能点是向量本身的备用容量,因此您可以使用shrink_to_fit()虽然我认为向量的索引/可写性增加了内存需求,但我可能把它们与python列表混淆了。