[英]Defining key of map as custom struct when implementing graph in C++
I am learning some graph algorithms and decided to implement a graph as an adjacency list.我正在学习一些图算法,并决定将图实现为邻接列表。 I am not very comfortable with C++ and I think I am making some syntactic mistakes on how to go about creating a graph represented by a map, with vertex
as the key and vector<vertex>
as the value.我对 C++ 不太满意,我认为我在如何创建由 map 表示的图形时犯了一些语法错误,并将vector<vertex>
vertex
键。 All of the following is in one file, with this at the top:以下所有内容都在一个文件中,此文件位于顶部:
#include <iostream>
#include <random>
#include <chrono>
#include <assert.h>
#include <algorithm>
#include <unordered_map>
using namespace std;
I realize it might be cleaner to use pointers, but I've committed to this approach for now: I have a vertex
object:我意识到使用指针可能更干净,但我现在已经致力于这种方法:我有一个vertex
object:
struct vertex
{
int number; // unique identifier - can be 0
int parent;
int distance_from_root;
char color; // one of 'w', 'b', 'g'
bool const operator==(const int num) const // define operator for handling map with this as key
{
return num == number;
}
};
Where I have added the operator
because I guess C++ needs some way to compare vertices when they're in a map, and so doing map[3]
should find the key that has 3
as key.number
I assume.我在哪里添加了operator
,因为我猜 C++ 需要一些方法来比较顶点,当它们位于 map 中时,因此执行map[3]
应该找到具有3
作为我假设的key.number
的键。 I only did this based on some SO question.我只是根据一些 SO 问题才这样做的。 Then this is my attempt to generate a graph (an adjacency list):然后这是我尝试生成一个图(邻接表):
unordered_map<vertex, <vector<vertex>>, vertexHasher> generate_random_graph(int nv)
{ // take as input the number of vertices in the map we're creating
// initialize vertex objects for use in map construction later
vector<vertex> all_vertices;
for (int i = 0; i < nv; ++i){
vertex v;
v.number = i;
all_vertices.push_back(v);
}
// initially didn't use vertexHasher but some SO question said we need it - not sure why
unordered_map<vertex, <vector<vertex>>, vertexHasher> adj_list;
for (int i = 0; i < nv; ++i){
vector<vertex> cur_v_conns; // vertices we want our new vertex to connect to
// create vector of vertices we want this one vertex to connect to
int n_conns_for_cur_v = rand_int(1, 5);
for (int j = 0; j < n_conns_for_cur_v; ++j){
vertex rand_v = all_vertices[rand_int(0, all_vertices.size()-1)];
bool exists = false;
for (auto conn: cur_v_conns){ // ensure we don't connect our next v to another one twice
if (conn.number == rand_v.number) exists = true;
} if (!exists) cur_v_conns.push_back(rand_v); // add rand_vertex as a connection to our current it it doesn't exist
}
adj_list.insert({ all_vertices[i]: cur_v_conns }); // add cur_v:c cur_v_conns to map
}
return adj_list;
}
In case it is relevant, here is vertexHasher
(not sure why this is there, but some SO question said we needed a custom hash function?)如果它是相关的,这里是vertexHasher
(不知道为什么会这样,但一些 SO 问题说我们需要一个自定义 hash function?)
struct vertexHasher
{
size_t operator()(const vertex &v) const
{
using std::hash;
using std::size_t;
using std::string;
return ((hash<string>()(v.number) ^ (hash<string>()(v.color) << 1)) >> 1) ^ (hash<int>()(v.distance_from_root) << 1);
}
};
I'm sure there are several little mistakes and I'd appreciate some elaboration on how one might approach a problem like this so I can learn some stuff about C++, but if you're looking for a concrete problem then I'm getting "expected a type identifier" error on the line of generate_random_graph
.我敢肯定有几个小错误,我希望能详细说明如何解决这样的问题,这样我就可以学习一些关于 C++ 的东西,但是如果你正在寻找一个具体的问题,那么我会得到“预期在generate_random_graph
行出现类型标识符”错误。 Thank you, And do you think this is a reasonable graph interpretation, by the by, or is an implementation using pointers and Edge
objects strictly better?谢谢,您认为这是一个合理的图形解释,还是严格使用指针和Edge
对象的实现更好?
-- EDIT -- Here is the complete compile error (but I suspect there are more structural problems than just these superficial errors) -- 编辑 -- 这是完整的编译错误(但我怀疑除了这些表面错误之外还有更多的结构性问题)
/Users/tanishqkumar/Desktop/cs124/algs/helpers.hh:101:23: error: expected expression
unordered_map<vertex, <vector<vertex>>, vertexHasher> generate_random_graph(int nv)
^
/Users/tanishqkumar/Desktop/cs124/algs/helpers.hh:101:38: error: expected '(' for function-style cast or type construction
unordered_map<vertex, <vector<vertex>>, vertexHasher> generate_random_graph(int nv)
~~~~~~~~~~~~~~^
/Users/tanishqkumar/Desktop/cs124/algs/helpers.hh:101:39: error: expected unqualified-id
unordered_map<vertex, <vector<vertex>>, vertexHasher> generate_random_graph(int nv)
^
/Users/tanishqkumar/Desktop/cs124/algs/helpers.hh:129:40: error: expected expression
void print_graph(unordered_map<vertex, <vector<vertex>>, vertexHasher> adj_list){
^
/Users/tanishqkumar/Desktop/cs124/algs/helpers.hh:129:55: error: expected '(' for function-style cast or type construction
void print_graph(unordered_map<vertex, <vector<vertex>>, vertexHasher> adj_list){
~~~~~~~~~~~~~~^
/Users/tanishqkumar/Desktop/cs124/algs/helpers.hh:129:40: error: expected expression
void print_graph(unordered_map<vertex, <vector<vertex>>, vertexHasher> adj_list){
^
/Users/tanishqkumar/Desktop/cs124/algs/helpers.hh:129:55: error: expected '(' for function-style cast or type construction
void print_graph(unordered_map<vertex, <vector<vertex>>, vertexHasher> adj_list){
~~~~~~~~~~~~~~^
/Users/tanishqkumar/Desktop/cs124/algs/helpers.hh:129:70: error: expected ')'
void print_graph(unordered_map<vertex, <vector<vertex>>, vertexHasher> adj_list){
^
/Users/tanishqkumar/Desktop/cs124/algs/helpers.hh:129:17: note: to match this '('
void print_graph(unordered_map<vertex, <vector<vertex>>, vertexHasher> adj_list){
^
/Users/tanishqkumar/Desktop/cs124/algs/helpers.hh:131:25: error: use of undeclared identifier 'adj_list'
for (int i = 0; i < adj_list.size(); ++i){ // print each el in adj_list
^
/Users/tanishqkumar/Desktop/cs124/algs/helpers.hh:134:29: error: use of undeclared identifier 'adj_list'
for (int j = 0; j < adj_list[i].size(); ++j){
^
/Users/tanishqkumar/Desktop/cs124/algs/helpers.hh:135:22: error: use of undeclared identifier 'adj_list'
if (j == adj_list[i].size()-1){
^
/Users/tanishqkumar/Desktop/cs124/algs/helpers.hh:136:25: error: use of undeclared identifier 'adj_list'
cout << adj_list[i][j].number << endl;
^
/Users/tanishqkumar/Desktop/cs124/algs/helpers.hh:139:25: error: use of undeclared identifier 'adj_list'
cout << adj_list[i][j].number << ", ";
^
/Users/tanishqkumar/Desktop/cs124/algs/graphs.cc:11:31: error: expected expression
typedef unordered_map<vertex, <vector<vertex>>, vertexHasher> adj_list_type;
^
/Users/tanishqkumar/Desktop/cs124/algs/graphs.cc:11:46: error: expected '(' for function-style cast or type construction
typedef unordered_map<vertex, <vector<vertex>>, vertexHasher> adj_list_type;
~~~~~~~~~~~~~~^
/Users/tanishqkumar/Desktop/cs124/algs/graphs.cc:11:47: error: expected unqualified-id
typedef unordered_map<vertex, <vector<vertex>>, vertexHasher> adj_list_type;
This compiles and does something.这会编译并做一些事情。 Perhaps it will help you proceed.也许它会帮助你继续。 I've added comments on the things I had to change in order to make it work.我已经添加了关于我必须更改以使其正常工作的内容的评论。
#include <iostream>
#include <random>
#include <chrono>
#include <assert.h>
#include <algorithm>
#include <unordered_map>
using namespace std;
std::random_device rd;
std::mt19937 random_generator(rd());
int rand_int(int low, int high)
{
return std::uniform_int_distribution<int>(low, high)(random_generator);
}
struct vertex
{
int number;
int parent;
int distance_from_root;
char color; // one of 'w', 'b', 'g'
// This needs to compare vertex with vertex, not vertex with int
bool const operator==(const vertex& rhs) const
{
return number == rhs.number;
}
};
std::ostream &operator<<(std::ostream &out, const vertex& v)
{
out << "[ number: " << v.number << " ]";
return out;
}
struct vertexHasher
{
size_t operator()(const vertex &v) const
{
// The template parameter needs to match the type.
return ((hash<int>()(v.number) ^ (hash<char>()(v.color) << 1)) >> 1) ^ (hash<int>()(v.distance_from_root) << 1);
}
};
unordered_map<vertex, vector<vertex>, vertexHasher> generate_random_graph(int nv)
{
vector<vertex> all_vertices;
for (int i = 0; i < nv; ++i)
{
vertex v;
v.number = i;
all_vertices.push_back(v);
}
unordered_map<vertex, vector<vertex>, vertexHasher> adj_list;
for (int i = 0; i < nv; ++i)
{
vector<vertex> cur_v_conns;
int n_conns_for_cur_v = rand_int(1, 5);
for (int j = 0; j < n_conns_for_cur_v; ++j)
{
vertex rand_v = all_vertices[rand_int(0, all_vertices.size() - 1)];
bool exists = false;
// Use const reference since the object doesn't need to be modified or copied
for (const auto& conn : cur_v_conns)
{
if (conn.number == rand_v.number)
{
exists = true;
// break since there's no reason to continue once a duplicate is found
break;
}
}
if (!exists)
{
cur_v_conns.push_back(rand_v);
}
}
// Use comma, not colon
adj_list.insert({ all_vertices[i], cur_v_conns });
}
return adj_list;
}
int main()
{
auto graph = generate_random_graph(10);
for (const auto &kvp : graph)
{
std::cout << "key: " << kvp.first << "\n";
std::string delim = "values: ";
for (const auto &v : kvp.second)
{
std::cout << delim << v;
delim = ", ";
}
std::cout << "\n\n";
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.