gpt4 book ai didi

c++ - 结构转发列表项消失了吗?

转载 作者:行者123 更新时间:2023-11-28 05:16:11 25 4
gpt4 key购买 nike

这段代码让我很紧张。已经调试了一段时间,不敢相信我对 C++ 的理解有多生疏。

我正在尝试对图形建模以运行一些简单的算法,但效果似乎不太好。每个顶点都包含一个到他的邻居的前向列表,但是当插入元素时它们显然存在......直到我到达打印功能;那时转发列表是空的。

我也尝试过使用 new 分配 forward_list,因为作用域可能是它的一个解释......那里也没有运气..

#include <iostream>
#include <vector>
#include <set>
#include <forward_list>
#include <fstream>

using namespace std;

typedef struct Vertex Vertex;

struct Vertex {
unsigned id;
forward_list<Vertex*>_next;

bool operator < (const Vertex &other) const { return id < other.id; };
};

typedef set<Vertex> Graph;
typedef vector<Vertex*> Index;
typedef pair<unsigned, unsigned> Edge;
typedef forward_list<Vertex*> Neighbors;


// Function: process_line()
// Purpose: process a specific line from the file.
// Params: line to process
Edge process_line(string line){
unsigned vertex_from;
unsigned vertex_to;

int idx = line.find(" ");

vertex_from = (unsigned)stoul(line.substr(0, idx));
vertex_to = (unsigned)stoul(line.substr(idx+1, line.length()));

return make_pair(vertex_from, vertex_to);
}


// Function: load_graph()
// Purpose: load graph from file in relation
// Params: path, and reference to graph and index
bool load_graph(string file_path, Graph &graph, Index &index){
string line;
ifstream file(file_path);
bool foundEmptyLine = false;

if(file.is_open()){
while(getline(file, line)){
if(line.empty()){
foundEmptyLine = true;
continue;
}

if(!foundEmptyLine){
// processing vertexes
Vertex *vertex = new Vertex;

vertex->id = stoul(line);
graph.insert(*vertex);
index.emplace_back(vertex);
}else{
//Processing relations
Edge edge = process_line(line);

Vertex* neighbor = index.at(edge.second);
Vertex* source = index.at(edge.first);

// Lookup edge in index
source->_next.emplace_front(neighbor);

// ITEMS PRESENT! <----------------------
}
}
file.close();
}else{
cout << "Unable to open " << file_path;
return false;
}

return true;
}


void print_graph(Graph &graph){
for(Graph::iterator it = graph.begin(); it != graph.end(); ++it){
Neighbors neighs = it->_next;

cout << "Node: " << it->id << " neighbors: " neighs.empty();

cout << endl;
}
}


// Entry point.
int main() {
Graph graph;
Index index;

load_graph("graph_1.txt", graph, index);
print_graph(graph);
}

最佳答案

这又是昨天的问题。

让我们尝试重述std::set

  • 自 C++11 起,std::setiterator 始终是const value_type 的迭代器。这是因为当我们更改 std::set 的条目时,需要将该条目放置在数据结构中的其他位置。
  • 当我们向 std::set 中插入内容时,会提供两个签名:

    pair<iterator,bool> insert (const value_type& val);
    pair<iterator,bool> insert (value_type&& val);

    但在任何情况下,插入都会复制移动 元素到容器中。

所以当你这样做的时候

Vertex *vertex = new Vertex;
vertex->id = stoul(line);
graph.insert(*vertex);
index.emplace_back(vertex);

首先你分配内存(顺便说一下,你永远不会删除!你会泄漏很多内存,你可以使用 valgrind 检查)。然后将顶点的拷贝插入 std::set 并将分配内存的指针插入 std::vector

当你以后做

Vertex* neighbor = index.at(edge.second);
Vertex* source = index.at(edge.first);

// Lookup edge in index
source->_next.emplace_front(neighbor);

您从 vector 中获取顶点(请记住,这是您使用 new 分配的顶点)。并将另一个顶点(也是动态分配的)插入到它的 std::forward_list 中。 但是:它们与您的std::set 中的顶点无关。

所以当您稍后通过您的 std::set 时:

for (Graph::iterator it = graph.begin(); it != graph.end(); ++it)

这与您在插入边时所做的完全无关 - 所有 std::forward_list 都是空的。

旁注:

  • 这是你必须在 C 中使用的东西,但不能在 C++ 中使用!

    typedef struct Vertex Vertex;
  • 这个你应该放在上面:

    typedef forward_list<Vertex*> Neighbors;

    在声明 _next 之后再声明 Neighbors 的类型是没有意义的,因为 _next 有这个类型。

  • 尽可能使用 const,尽可能使用 cbegin/cend(我昨天已经告诉过你),例如:

    for(Graph::iterator it = graph.cbegin(); it != graph.cend(); ++it){

    这里没有区别,但是如果你在某个时候改变了 graph 的类型,begin() 可能会返回一个迭代器到 value_type 而不是 const value_type

关于c++ - 结构转发列表项消失了吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42597237/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com