Структурировать пункты списка форвардов исчезают?
Этот кусок кода действует мне на нервы. Некоторое время я отлаживал его, не могу поверить, насколько я ржавый на C++.
Я пытаюсь смоделировать график для запуска некоторых простых алгоритмов, но, похоже, это не очень хорошо работает. Каждая вершина содержит прямой список своих соседей, однако при вставке элементов они явно присутствуют. До тех пор, пока я не достигну функции печати; в это время список пересылки пуст.
Я попытался выделить forward_list, используя new aswell, так как определение области видимости может быть объяснением для этого.. Там тоже не повезло..
#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);
}
2 ответа
Это опять та же проблема, что и вчера.
Попробуем повторить std::set
- Начиная с C++11
iterator
изstd::set
всегда итератор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);
Вы берете вершину из своего вектора (помните, это вершина, которую вы наделили 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;
Не имеет смысла объявлять тип
Neighbors
после того как вы объявили_next
, так как_next
имеет этот тип.использование
const
везде, где вы можете, иcbegin
/cend
где вы можете (я уже говорил вам это вчера), например:for(Graph::iterator it = graph.cbegin(); it != graph.cend(); ++it){
Это не имеет значения здесь, но если вы измените тип
graph
в какой-то момент,begin()
может вернуть итераторvalue_type
вместоconst value_type
Изменен график, чтобы сохранить ссылки на существующие вершины. Я все еще не уверен, почему это исправило это - но чувствовал, что хотел дать хедз-ап.