1.簡單
我忘了我測沒測過了,這個比下面的方法輕便多了。
class Edge
{
public:
int weight;//權重
int from;
int to;
Edge(int weightt, int fromm, int too)
{
weight = weightt;
from = fromm;
to = too;
}
};
void TOGetEdge(vector<vector<int>>a, vector<Edge>&edge)//有向圖,a是圖的結構體,edge是邊的結構體,需要在外面定義,傳遞引用進來。
{
int n = a.size();
for (int i = 0; i<n; ++i)
for (int j = 0; j<n; ++j)
if (-1 != a[i][j])
edge.push_back(*new Edge(a[i][j], i, j));
}
void NOGetEdge(vector<vector<int>>a, vector<Edge>&edge)//無向圖
{
int n = a.size();
for (int i = 0; i<n; ++i)
for (int j = i + 1; j<n; ++j)
if (-1 != a[i][j])
edge.push_back(*new Edge(a[i][j], i, j));
}
2.複雜
左神寫了一個超級厲害的讀圖程序。圖包括點集和邊集,一個點的結構體包括權值、入度、出度、出的邊有哪些,出的邊都連接哪些節點。邊集包括邊的權重、邊的起點終點和num(這個num貌似是邊的編號,我的讀圖程序中基本就沒用)。
程序在寫的時候差別比較大,左神的Java用起來比較簡單,首先unordered_map的key是不直接支持結構體的,如果想要支持就得自己設置哈希函數和哈希的比較規則,畢竟結構體的比較,編譯器是沒法自己做的。自定義哈希比較繁瑣,stl中定義的哈希函數中沒有帶結構體指針的,只有基本類型。functional頭文件中的hash函數可以做到,或者boost中的hash_combine函數。我很執拗的就是不想用boost,最後發現functional中的hash函數中最後hash<T>就是其它類型。至於我用到的一個int和兩個結構體指針各自的哈希是怎麼組合的,我查看的是網上的說法,異或和移位操作來設計哈希函數比較合適。
最後一個問題就是我在定義Node類的時候需要用到Edge類的對象,定義Edge類的對象時需要用到Node類的對象,但是我如果先定義Node類,會出現Edge未定義的錯誤,所以我在定義Edge類的時候定義的不是對象,而是對象的指針。
下面這個程序我測試了一個圖讀取成功了,應該問題不大,但是做題我沒用過,這個太繁瑣了。
#include<iostream>
#include<vector>
#include<list>
#include<unordered_map>
#include<unordered_set>
#include <string>
#include<functional>
#include<string.h>
using namespace std;
class Edge;
class Node
{
public:
int value;//權值
int in;//入度
int out;//出度
list<Edge> edge;//出的邊
list<Node> nextnode;//出的邊連的節點
Node(int valuee)
{
value = valuee;
in = 0;
out = 0;
}
};
class Edge
{
public:
int weight;//權重
Node *from;//有向圖的起點
Node *to;//有向圖的終點
int num;
Edge(int weightt, Node *fromm, Node *too)
{
weight = weightt;
from = fromm;
to = too;
num = -1;
}
};
struct func //hash 函數
{
size_t operator()(const Edge a) const
{
return ((hash<int>()(a.weight)
^ (hash<Node*>()(a.from) << 1)) >> 1)
^ (hash<Node*>()(a.to) << 1);
}
};
struct cmp_fun //比較函數 ==
{
bool operator()(const Edge &a, const Edge &b) const
{
return memcmp(&a, &b, sizeof(a)) == 0 ? true:false;
}
};
struct Graph//整個圖
{
public:
unordered_map<int, Node>node;
unordered_set<Edge, func,cmp_fun>edge;
};
Graph *graph = new Graph;
void ReadGraph(vector<vector<int>>a)//讀圖程序
{
int n = a.size();
for (int i = 0; i<n; ++i)
{
int weight = a[i][0];
int from = a[i][1];
int to = a[i][2];
if (graph->node.find(from) == graph->node.end())//如果from點沒有就加入
graph->node.insert(pair<int, Node>(from, *new Node(from)));
if (graph->node.find(to) == graph->node.end())//如果to點沒有就加入
graph->node.insert(pair<int, Node>(to, *new Node(to)));
//上面兩行代碼過後不管from和to有沒有就都有了
//Node fromNode = graph->node.find(from)->second;//在哈希表中提出from點
//Node toNode = graph->node.find(to)->second;//提出to點
Edge *newedge = new Edge(weight, &(graph->node.find(from)->second), &(graph->node.find(to)->second));//建立一條邊
graph->node.find(from)->second.nextnode.push_back(to);//from節點的next節點是to
//原型是fromNode.nextnode.push_back(to);我寫成這麼麻煩是沒有辦法,需要直接修改類中的數據
graph->node.find(from)->second.out++;//from的出度++
//原型是fromNode.out++;
graph->node.find(to)->second.in++;//to節點的入度++
//原型是toNode.in++;
graph->node.find(from)->second.edge.push_back(*newedge);//把這條邊加入到from點的邊集中
graph->edge.insert(*newedge);//把這條邊加入到圖中
}
}
int main(void)
{
// int n = 8;
vector<vector<int>>a;
for (int i = 0; i<8; ++i)
{
vector<int>temp;
for (int j = 0; j<3; ++j)
{
int xx;
cin >> xx;
temp.push_back(xx);
}
a.push_back(temp);
}
ReadGraph(a);
//map<int,Node> ::iterator p=graph->node.begin();//p是map的迭代器,並不是Node的,所以獲取node需要p->second
//for(;p!=graph->node.end();++p)//遍歷所有的點
return 0;
}