兩個菊厲害的讀圖程序

文章目錄

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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章