【數據結構】圖的模擬實現(臨接矩陣法)

什麼是圖:

圖是由頂點集合及頂點間的關係組成的一種數據結構:G = (V , E), 其中頂點集合V={ x| x屬於某個數據對象集} 是有窮非空集合;E = {(x,y) | x,y屬於V } 或者 E = { (x , y ) | x,y屬於V && Path( x , y) }是頂點間關係的有窮集合,也叫做邊的集合。(x, y)表示 x 到 y 的一條雙向通路,即(x , y)是無方向的。

圖的相關概念:

(1)頂點和邊: 圖中節點稱爲頂點,第i個節點記作Vi 。兩個頂點Vi 和Vj 相關聯稱作頂點Vi 和頂點 Vj 之間有一條邊,圖中的第k條邊記作(Vi ,Vj)或 < Vi
,Vj>。

(2)有向圖和無向圖: 在有向圖中,頂點對< x, y >是有序的,頂點對< x , y>稱爲頂點x到頂點y 的一條邊,< x,y> 與 < y,x >是兩條不同的邊。 在無向圖中,頂點對< x,y>是無序的,< x, y> 與 < y,x >表示同一條邊。
這裏寫圖片描述

(3)完全圖:在有n個頂點的無向圖中,若有 n*(n-1) / 2條邊,即任意兩個頂點之間有且僅有一條邊,則此圖爲無向完全圖。在n個頂點的有向圖中,若有 n *(n-1) 條邊,即任意兩個頂點之間有且僅有方向相反的邊,則稱此圖爲有向完全圖。
這裏寫圖片描述

(4)鄰接頂點: 在無向圖G中,若( u,v) 是 E (G) 中的一條邊,則稱 u和 v 互爲鄰接頂點,並稱邊(u,v)依附於頂點u 和 v ;在有向圖G中,若< u,v >是E(G)中的一條邊,則稱頂點u鄰接到v,頂點v鄰接自頂點u,並稱邊< u,v>與頂點u和頂點v相關聯。

(5)頂點的度: 頂點v的度是指與它相關聯的邊的條數,記作deg(v) 。在有向圖中,頂點的度等於該頂點的入度與出度之和,其中頂點v的入度是以v爲終點的有向邊的條數,記作indev(v); 頂點v的出度是以v爲起始點的有向邊的條數,記作outdev(v) 。因此:dev(v)=indev(v)+outdev(v);
對於無向圖,頂點的度等於該頂點的入度和出度,即dev(v)=indev(v)=outdev(v)

(6) 路徑: 在圖G=( V , E )中,若從頂點Vi出發有一組邊使其可達到頂點Vj,則稱頂點Vi到頂點Vj的頂點序列爲從頂點Vi到頂點Vj的路徑。

(7) 權:邊附帶的數據信息。
這裏寫圖片描述

(8)路徑長度: 對於不帶權的圖,一條路徑的路徑長度是指該路徑上的邊的條數;對於帶權的圖,一條路徑的路徑長度是指該路徑上各個邊權值的總和。

(9)簡單路徑與迴路:若路徑上各頂點V1,V2,V3,…,Vm均不重複,則稱這樣的路徑爲簡單路徑。若路徑上第一個頂點V1和最後一個頂點Vm重合,則稱這樣的路徑爲迴路或環。

(10)子圖: 設圖G={ V ,E}和圖G1={V1,E1},若V1屬於E,則稱G1是G的子圖。
這裏寫圖片描述

(11)連通圖: 在無向圖中,若從頂點V1到頂點V2有路徑,則稱頂點V1與頂點V2是連通的。如果圖中任意一對頂點都是連通的,則稱此圖爲連通圖。
這裏寫圖片描述

(12)強連通圖:在有向圖中,若在每一對頂點Vi和Vj之間都存在一條從Vi到Vj的路徑,也存在一條從Vj到Vi的路徑,則稱此圖是強連通圖。
這裏寫圖片描述

(13)生成樹:一個連通圖的最小連通子圖稱作該圖的生成樹。有n個頂點的連通圖的生成樹有n個頂點和n-1條邊。
這裏寫圖片描述

圖的模擬實現:

鄰接矩陣法:
將所有的頂點信息組織成一個頂點表,然後利用一個矩陣來表示各頂點之間的鄰接關係。
使用二維數組表示一個矩陣,G.Edge[n][n]。
這裏寫圖片描述
w( i , j ) 表示的是權值。
這裏寫圖片描述

代碼實現:

#pragma once
#include<iostream>
#include<vector>
#include<assert.h>

using namespace std;

//臨接矩陣法模擬實現圖
template<class V,class W,bool digraph=false>
class Graph
{
public:
    Graph(V* array, size_t size)
        :_v(array, array + size)
    {
        _edges.resize(size);
        size_t i = 0;
        for (i = 0; i < size; i++)
        {
            _edges[i].resize(size);
        }
    }
    //添加邊源目標權值
    void Addedges(const V& src, const V& dst, const W& w)
    {
        size_t srcIndex = GetVertexIndex(src);
        size_t dstIndex = GetVertexIndex(dst);

        _edges[srcIndex][dstIndex] = w;    //賦權值
        if (digraph == false)          //是無向圖
        {
            _edges[dstIndex][srcIndex] = w;
        }
    }
    //獲取頂點的度
    int getCount(const V& v)
    {
        int count = 0;
        size_t i = 0;
        int set = GetVertexIndex(v);
        for (i = 0; i < _v.size(); i++)
        {
            if (_edges[set][i] !=0)
                count++;
        }
        return count;
    }

    //打印
    void Display()
    {
        size_t i = 0,j=0;
        size_t size= _v.size();
        for (i = 0; i < size; i++)
        {
            for (j = 0; j < size; j++)
            {
                printf("%2d ",_edges[i][j]);
            }
            cout << endl;
        }
        cout << endl;
    }
private:
    //獲取頂點下標
    size_t GetVertexIndex(const V& v)
    {
        size_t i = 0;
        for (i = 0; i < _v.size(); i++)
        {
            if (v == _v[i])
                return i;
        }
        assert(false);
        return -1;
    }

private:
    vector<V> _v;     //頂點集合
    vector<vector<W>> _edges;    //二維數組鄰接矩陣
};

void test()
{
    char* p = "ABCDE";
    Graph<char, int,true> g(p, strlen(p));
    g.Addedges('A', 'D', 10);
    g.Addedges('A', 'E', 20);
    g.Addedges('B', 'C', 10);
    g.Addedges('B', 'D', 20);
    g.Addedges('B', 'E', 30);
    g.Addedges('C', 'E', 40);

    g.Display();
    cout << g.getCount('B') << endl;
}

運行結果:
(有向圖)
這裏寫圖片描述

(無向圖)
這裏寫圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章