數據結構(五)圖---圖的存儲結構5種


一:圖的抽象數據類型

ADT 圖(Graph)

Data
    頂點的有窮非空集合和邊的集合

Operation
    CreateGraph(*G,V,VR):按照頂點集V和邊弧集VR的定義構造圖G
    DestroyGraph(*G):圖G存在則銷毀
    LocateVex(G,u):若圖G中存在頂點u,則返回圖中位置
    GetVex(G,v):返回圖中頂點v的值
    PutVex(G,v,value):將圖G中頂點v賦值給value
    FirstAdjVex(G,*v):返回頂點v的一個鄰接頂點,若頂點在G中無鄰接頂點則返回空
    NextAdjVex(G,v,*w):返回頂點v相對於頂點w的下一個鄰接頂點,若w是v的最后一個鄰接點則返回空
    InsertVex(*G,v):在圖G中增加新頂點v
    DeleteVex(*G,v):刪除圖G中頂點v及其相關的弧
    InsertArc(*G,v,w):在圖G中添加弧<v,w>,若G是無向圖,還需要添加對稱弧<w,v>
    DeleteArc(*G,v,w):在圖G中刪除弧<v,w>,若G是無向圖,則需要刪除對稱弧<w,v>
    DFSTraverse(G):對圖G中進行深度優先遍歷,在遍歷過程對每個頂點調用
    HFSTraverse(G):對圖G中進行廣度優先遍歷,在遍歷過程對每個頂點調用
endADT

二:圖的存儲結構討論

對於線性表來說,是一對一的關系,所以用數組或者鏈表均可以簡單存放。
對於樹結構是一對多的關系,所以我們要將數組和鏈表的特性結合在一起才能更好的存放。
對於圖來說,是多對多的情況,另外圖上的任意一個頂點都可以被看做是第一個頂點,任一頂點的鄰接點之間也不存在次序關系
如下圖:實際是一個圖結構,只不過頂點位置不同。

由於圖的結構復雜,任意兩個頂點之間都可能存在聯系,因此無法以數據元素在內存中的物理位置來表示元素之間的關系,也就是說,圖不可能用簡單的順序存儲結構來表示。
內存物理位置是線性的,圖的元素關系是平面的。
雖然我們可以向樹結構中說到的那樣使用多重鏈表,但是我們需要先確定最大的度,然后按照這個度最大的頂點設計結點結構,若是每個頂點的度數相差較大,就會造成大量的存儲單元浪費。

三:圖的存儲結構(1)---鄰接矩陣

考慮到圖是由頂點和邊(弧)兩部分組成的,合在一起是比較困難的,那就很自然的考慮到分為兩個結構來分別存儲
頂點因為不區分大小,主次,所以用一個一維數組來存儲時不錯的選擇。 而邊或弧由於是頂點與頂點之間的關系,所以我們最好使用二維數組來存儲
圖的鄰接矩陣存儲方式是用兩個數組來表示圖。一個一維數組存儲圖中頂點信息,一個二維數組(稱為鄰接矩陣)存儲圖中的邊或弧的信息。

(一)無向圖

其中1表示兩個頂點之間存在關系,0表示無關,不存在頂點間的邊。
對稱矩陣:就是n階矩陣滿足a[i][j]=a[j][i](0<=i,j<=n)。即從矩陣的左上角到右下角的主對角線為軸,右上角的源與左下角相對應的元都是相等的。
根據這個矩陣,我們可以很容易的知道圖中的信息。
1.我們要判定容易兩頂點是否有邊無邊就非常容易了。 2.我們要知道某個頂點的度,其實就是這個頂點vi在鄰接矩陣中第i行(或第i列)的元素之和。比如上圖頂點v1的度就是1+0+1+0=2 3.求頂點vi的所有鄰接點就是將矩陣第i行元素掃描一遍,arc[i][j]為1就是鄰接點

(二)有向圖

對於上面的無向圖,二維對稱矩陣似乎浪費了一半的空間。若是存放有向圖,會更大程度利用起來空間

其中頂點數組是一樣的和無向圖,弧數組也是一個矩陣,但因為是有向圖,所以這個矩陣並不對稱:例如v1->v0有弧,arc[1][0]=1,而v0到v1沒有弧,所以arc[0][1]=0。
另外有向圖,要考慮入度和出度,頂點v1的入度為1,正好是第v1列的各數之和,頂點v1的出度為2,正好是第v2行的各數之和

(三)網

每條邊上帶有權的圖就叫做網

這里‘∞’表示一個計算機允許的,大於所有邊上權值的值

(四)實現無向網圖創建

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MAXVEX 100    //最大頂點數
#define INFINITY 65535    //用65535表示∞

typedef char VertexType;    //頂點類型,字符型A,B,C,D...
typedef int EdgeType;    //邊上權值類型10,15,...

typedef struct
{
    VertexType vers[MAXVEX];    //頂點表
    EdgeType arc[MAXVEX][MAXVEX];    //鄰接矩陣,可看作邊表
    int numVertexes, numEdges;    //圖中當前的頂點數和邊數
}MGraph;

void CreateMGraph(MGraph* G)
{
    int i, j, k, w;
    printf("please input number of vertex and edge:\n");
    scanf("%d,%d", &G->numVertexes, &G->numEdges);    //輸入頂點數和邊數
    getchar();    //可以獲取回車符
    for (i = 0; i < G->numVertexes; i++)    //讀入頂點信息,建立頂點表
        scanf("%c", &G->vers[i]);
    getchar();    //可以獲取回車符
    for (i = 0; i < G->numVertexes;i++)
        for (j = 0; j < G->numVertexes;j++)
            G->arc[i][j] = INFINITY;    //鄰接矩陣初始化

    for (k = 0; k < G->numEdges;k++)    //讀入numEdges條邊,建立鄰接矩陣
    {
        printf("input edge(vi,vj) row(i),col(j),weight(w):\n");
        scanf("%d,%d,%d", &i, &j, &w);    //輸入邊(vi,vj),以及上面的權值
        getchar();    //可以獲取回車符
        G->arc[i][j] = w;
        G->arc[j][i] = G->arc[i][j];    //因為是無向圖,所有是對稱矩陣
    }
}

int main()
{
    MGraph MG;
    CreateMGraph(&MG);

    system("pause");
    return 0;
}
n個頂點,e條邊創建無向網圖,時間復雜度是O(n+n^2+e),初始化時耗費了O(n^2)

 

四:圖的存儲結構(2)---鄰接表

上面的鄰接矩陣是一種不錯的圖存儲結構,便於理解,但是當我們的邊數相對於頂點較少的圖,這種結構是存在對存儲空間的極大的浪費。

我們可以考慮使用鏈表來動態分配空間,避免使用數組一次分配而造成空間浪費問題。
同樹中,孩子表示法,我們將結點存放入數組,對結點的孩子進行鏈式存儲,不管有多少孩子,都不會存在空間浪費。這種思路也適用於圖的存儲。我們把這種數組與鏈表相結合的存儲方法稱為鄰接表

鄰接表處理辦法

1.圖中頂點用一個一維數組。當然,頂點也可以用單鏈表來存儲,不過數組可以較容易的讀取頂點信息,更加方便。另外,對於頂點數組中,每個數據元素還需要存儲指向第一個鄰接點的指針,以便於查找該頂點的邊信息
2.圖中每個頂點vi的所有鄰接點構成一個線性表,由於鄰接點的個數不定,所以用單鏈表存儲,無向圖稱為頂點vi的邊表,有向圖則稱為頂點vi作為弧尾的出邊表

(一)無向圖

這樣的結構,對於我們要獲得圖的相關信息也是很方便。比如:
我們要獲取某個頂點的度,就要去查找這個頂點的邊表中結點的個數。 我們要判斷vi到vj是否存在邊,只需要測試vi的邊表鏈表中是否存在結點vj的下標j即可。 我們若是要獲取頂點的所有鄰接點,就是對此頂點的邊表進行遍歷。

(二)有向圖

有向圖由於有方向,我們是以頂點為弧尾來存儲邊表的,這樣很容易就可以得到每個頂點的出度。但是由於有時也需要確定頂點的入度或以頂點作為弧頭的弧,我們可以建立一個有向圖的逆鄰接表,即對每個頂點vi都建立一個鏈接為vi為弧頭的表

(三)帶權值的網圖

我們可以在邊表結點定義中再增加一個weight數據域,存儲權值信息即可

(四)實現無向網圖

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MAXVEX 100    //最大頂點數

typedef char VertexType;    //頂點類型,字符型A,B,C,D...
typedef int EdgeType;    //邊上權值類型10,15,...

typedef struct EdgeNode    //邊表結點
{
    int adjvex;            //鄰接點域,存放該頂點對應的下標
    int weight;            //用於存放權值,對於非網圖可以不需要
    struct EdgeNode* next;    //鏈域,指向下一個鄰接點
}EdgeNode;

typedef struct VertexNode   //頂點表結點
{
    VertexType data;    //頂點域,存儲頂點信息
    EdgeNode* firstedge;    //邊表頭指針
}VertexNode,AdjList[MAXVEX];

typedef struct
{
    AdjList adjList;    //鄰接表數組
    int numVertexes, numEdges;    //圖中所存儲的頂點數和邊數
}GraphAdjList;

void CreateALGraph(GraphAdjList* G)
{
    int i, j ,k,w;
    EdgeNode *e;
    printf("please input number of vertex and edge:\n");
    scanf("%d,%d",&G->numVertexes,&G->numEdges);    //輸入頂點數和邊數
    getchar();    //可以獲取回車符
    for (i = 0; i < G->numVertexes;i++)    //輸入頂點信息
    {
        scanf("%c", &G->adjList[i].data);    //輸入頂點信息
        G->adjList[i].firstedge = NULL;    //將邊表置為空
    }
    getchar();    //可以獲取回車符
    for (k = 0; k < G->numEdges;k++)
    {
        printf("input edge(vi,vj) vertexs series and the weight:\n");
        scanf("%d,%d,%d", &i, &j,&w);
        getchar();
        //由於是無向圖,對稱矩陣,當我們設置邊以后,需要在兩個地方設置結點
        e = (EdgeNode *)malloc(sizeof(EdgeNode));
        //使用頭插法將數據插入(主要是頭插法方便),我們插入不需要考慮順序,因為鏈表結點都是與數組頂點相連接的
        e->adjvex = j;
        e->next = G->adjList[i].firstedge;    
        e->weight = w;
        G->adjList[i].firstedge = e;

        e = (EdgeNode*)malloc(sizeof(EdgeNode));
        e->adjvex = i;
        e->next = G->adjList[j].firstedge;
        e->weight = w;
        G->adjList[j].firstedge = e;
    }
}

int main()
{
    GraphAdjList gl;
    CreateALGraph(&gl);
    system("pause");
    return 0;
}

注意:上面的兩種存儲結構是針對頂點,下面的三種存儲結構是針對邊

五:圖的存儲結構(3)---十字鏈表

我們想要知道出度方向的頂點,可以使用鄰接表,我們要了解入度就需要使用逆鄰接表。但是我們既想要了解入度有想要了解出度,那么我們該如何處理?
這時就需要使用到有向圖的一種存儲方法:十字鏈表

頂點表結點結構

firstin表示入邊表頭指針,指向該頂點的入邊表中第一個結點。
firstout表示出邊表頭指針,指向該頂點的出邊表中第一個結點。

邊表結點結構

其中tailvex是指弧起點頂點表的下標,headvex是指弧終點頂點表的下標。
headlink是指入邊表指針域,指向終點相同的下一條邊taillink是指邊表指針域,指向起點相同的下一條邊。
如果是網,我們還要在其中加入權值域,來存儲權值

我們可以看做橫向是出度,豎向是入度
頂點的出度和入度。除了結構復雜一點外,其實創建圖算法的時間復雜度和鄰接表是相同的,因此很好的應用在有向圖中。
注意:整張圖的出度和入度是一致的(不是某個頂點,而是這張圖)

代碼實現

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MAXVEX 100    //最大頂點數

typedef char VertexType;    //頂點類型,字符型A,B,C,D...
typedef int EdgeType;    //邊上權值類型10,15,...

typedef struct OLNode    //十字鏈表結點
{
    int tailvex, headvex;    //表示兩個頂點下標,構成了一條邊。tailvex是箭頭尾,弧尾,headvex是箭頭頭,是弧頭
    int weight;            //用於存放權值,對於非網圖可以不需要
    struct OLNode* taillink;    //十字鏈域,指向下一個鄰接點,是出度方向
    struct OLNode* headlink;    //十字鏈域,指向下一個鄰接點,是入度方向
}OLNode;

typedef struct VertexNode   //頂點表結點
{
    VertexType data;    //頂點域,存儲頂點信息
    OLNode* firstin;    //邊表頭指針,入度
    OLNode* firstout;    //邊表頭指針,出度
}VertexNode, CrossList[MAXVEX];

typedef struct
{
    CrossList adjList;    //鄰接表數組
    int numVertexes, numEdges;    //圖中所存儲的頂點數和邊數(出度指針和入度指針是和邊數是一致的)
}GraphCrossList;

void CreateCrossGraph(GraphCrossList* G)
{
    int i, j ,k,w;
    OLNode *e;
    printf("please input number of vertex and edge:\n");
    scanf("%d,%d",&G->numVertexes,&G->numEdges);    //輸入頂點數和邊數
    getchar();    //可以獲取回車符
    for (i = 0; i < G->numVertexes;i++)    //輸入頂點信息
    {
        scanf("%c", &G->adjList[i].data);    //輸入頂點信息
        G->adjList[i].firstin = NULL;    //將邊表置為空
        G->adjList[i].firstout = NULL;    //將邊表置為空
    }
    getchar();    //可以獲取回車符

    //先循環獲取出度結點,出度數和入度數是一致的
    for (k = 0; k < G->numEdges;k++)
    {
        printf("Out-->input edge(vi,vj) vertexs series and the weight:\n");
        scanf("%d,%d,%d", &i, &j,&w);
        getchar();
        //創建十字鏈表結點
        e = (OLNode *)malloc(sizeof(OLNode));
        //使用頭插法將數據插入(主要是頭插法方便),我們插入不需要考慮順序,因為鏈表結點都是與數組頂點相連接的
        e->tailvex = i;
        e->headvex = j;
        e->weight = w;
        e->taillink = G->adjList[i].firstout;
        G->adjList[i].firstout = e;
    }

    //再循環獲取入度結點,在上面的出度結點建立了所有結點的基礎上,我們再建立入度指針指向
    //例如我們要獲取v0的入度v1,我們先輸入入度點0,再輸入出度點1,不需要權值,權值在上面對有向圖都賦值了
    //我們進行第二個指針v0的入度v2,我們使用相同輸入,但是開始使用頭插法修改鏈表firstin指向
    for (k = 0; k < G->numEdges; k++)
    {
        printf("In-->input edge(vi,vj) vertexs series:\n");
        scanf("%d,%d", &i, &j);
        getchar();
        //根據上面的輸入,我們將當前的頂點域firstin指向我們獲取的新的入度域
        //先找入度域
        e = G->adjList[j].firstout;
        while (e->headvex!=i)
            e = e->taillink;    //循環十字鏈表結點,獲取我們要的入度結點
        //使用頭插法插入入度指針域
        e->headlink = G->adjList[i].firstin;
        G->adjList[i].firstin = e;
    }
}

int main()
{
    GraphCrossList gl;
    CreateCrossGraph(&gl);
    gl;
    system("pause");
    return 0;
}

六:圖的存儲結構(4)---鄰接多重表

鄰接多重表是對無向圖的存儲結構的優化

問題:

對於無向圖的鄰接表,我們更加關注的重點是頂點,那么是不錯的選擇,但是我們要是關注的是邊的操作。
比如:刪除一條邊,那么我們的操作將變得復雜,我們需要找到這條邊的兩個頂點,方便去其鏈表中刪除所表示的邊。稍微有點麻煩。

改進:

 

我們只出現無向圖中對應條數的邊表結點,其他的結構,我們全部由指針來聯系,所以當我們想要刪除一條邊時,就只需要刪除對應的邊表結點。指向她的指針會置為空,他自己產生的指針會消失。就完成了對邊的操作。

例如上圖,我們若是使用鄰接表:是要10個頂點結點去表示5條邊,而我們若是使用鄰接多重表,只需要5個邊結點即可。刪除一條邊就不存在重復操作

定義

鄰接多重表結構

其中ivex和jvex是指某條邊依附的兩個頂點在頂點表中的下標ilink指向依附頂點ivex的下一條邊,jlink指向依附頂點jvex的下一條邊。
如上圖有4個頂點和5條邊,先將邊表結點畫出來。由於是無向圖,所以ivex,jvex正反過來都可以,為了繪圖方便,都將ivex值設置的與一旁的頂點下標相同

1.將邊表結點畫出來

2.開始連線

首先連線的(1)(2)(3)(4)是將頂點的firstedge指向一條邊,頂點下標要與ivex的值相同。

接着,由於頂點v0的(v0,v1)邊的鄰邊有(v0,v3)和(v0,v2)。因此(5)(6)的連線就是滿足指向下一條依附於頂點v0的邊的目標,注意ilink指向的結點的jvex(ivex)一定要與它本身的ivex的值相同
注意ilink指向的結點的jvex(ivex)一定要與它本身的ivex的值相同。而且為了方便,我們和jvex相同,那么全部指向都要與之一樣

同理,連線(7)就是指(v1,v0)這條邊,它是相當於頂點v1指向(v1,v2)邊后的下一條。

v2有三條邊依附,所以(3)之后就有了(8)(9)。

連線(10)就是頂點v3在連線(4)之后的下一條邊

左圖一共有5條邊,所以右圖有10條連線,完全符合預期。

總結

鄰接多重表與鄰接表的差別,僅僅是在於同一條邊在鄰接表中用兩個邊表結點表示,而在鄰接多重表中只有一個結點。這樣對邊的操作就方便多了,
若要刪除左圖的(v0,v2)這條邊,只需要將右圖的(
6)(9)的鏈接指向改為^即可。

代碼實現前的思考:

MMP,怎么就想不出來用什么方法去存儲這些邊呢?頂點和邊不對應呀....吐血....,去網上找找其他關於鄰接多重表的信息吧

數據結構之圖(2-2)【鄰接多重表】適用於無向圖

無向圖的鄰接多重表存儲結構

這兩篇文章來了思路,將表的結構修改一下,我們只需要保證鄰接多重表的根本,就是創建邊表,而不是創建頂點表,因為頂點表是邊表的兩倍,在刪除時會導致重復操作,而我們的邊表只需要創建對應邊數的結點,刪除某條邊,就刪除對應結點即可。不需要重復操作。

 

 

上面這種表示方法,但是好像沒說清楚為啥這么排列。
於是決定測試將對應頂點的鄰接邊全部放入頂點后面

步驟一:先排序第一個頂點的所有鄰接邊

步驟二:我們再排序第二個頂點的所有鄰接邊

步驟三:我們接着排序第三個頂點的所有鄰接邊

步驟四:開始排序最后一個頂點所有鄰接邊

 

 通過上面排序,我們可以獲取所有鄰接點和鄰接邊

 按照上面來實現代碼

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MAXVEX 100    //最大頂點數

typedef char VertexType;    //頂點類型,字符型A,B,C,D...
typedef int EdgeType;    //邊上權值類型10,15,...

typedef struct ENode    //十字鏈表結點
{
    int ivex, jvex;    //表示兩個頂點下標,構成了一條邊。
    int weight;            //用於存放權值,對於非網圖可以不需要
    struct ENode* ilink;    //鄰接多重表,指向下一個鄰接點,
    struct ENode* jlink;    //鄰接多重表,指向下一個鄰接點,
}ENode;

typedef struct VertexNode   //頂點表結點
{
    VertexType data;    //頂點域,存儲頂點信息
    ENode* firstedge;    //邊表頭指針
}VertexNode, AMLList[MAXVEX];

typedef struct
{
    AMLList adjList;    //鄰接多重表數組
    int numVertexes, numEdges;    //圖中所存儲的頂點數和邊數
}AMLGraphList;

//根據ivex找到第幾行,我們去前面幾行查找,jvex獲取下標
ENode* GetNode(AMLGraphList* G,int ivex,int jvex)
{
    int i;
    ENode *e;
    for (i = ivex-1; i >=0;i--)
    {
        e = G->adjList[i].firstedge;
        while (e)
        {
            if (e->jvex==jvex)
            {
                return e;
            }
            e = e->ilink;
        }
    }

    return NULL;
}

void CreateAMLGraph(AMLGraphList* G)
{
    int i, j, k, w,flag;
    ENode *e;
    ENode *tempNode;
    printf("please input number of vertex and edge:\n");
    scanf("%d,%d", &G->numVertexes, &G->numEdges);    //輸入頂點數和邊數
    getchar();    //可以獲取回車符
    for (i = 0; i < G->numVertexes; i++)    //輸入頂點信息
    {
        scanf("%c", &G->adjList[i].data);    //輸入頂點信息
        G->adjList[i].firstedge = NULL;    //將邊表置為空
    }
    getchar();    //可以獲取回車符

    //先循環獲取邊信息。創建所有邊信息,放在對應的頂點后面,
    for (k = 0; k < G->numEdges; k++)
    {
        printf("Out-->input edge(vi,vj) vertexs series and the weight:\n");
        scanf("%d,%d,%d", &i, &j, &w);
        getchar();
        //創建鄰接多重表結點
        e = (ENode *)malloc(sizeof(ENode));
        //使用頭插法將數據插入(主要是頭插法方便),我們插入不需要考慮順序,因為鏈表結點都是與數組頂點相連接的
        e->ivex = i;
        e->jvex = j;
        e->weight = w;
        e->ilink = G->adjList[i].firstedge;
        e->jlink = NULL;
        G->adjList[i].firstedge = e;
    }

    //開始連接多張表之間的關系,並且判斷ilink和jlink,從第二個頂點開始
    for (i = 1; i < G->numVertexes;i++)
    {
        e = G->adjList[i].firstedge;
        if (e)
        {
            flag = 0;    //用來標識是不是最后一個結點
            while (e&&!flag)    //需要將最后一個單獨處理
            {
                if (e->ilink == NULL)
                {
                    tempNode = GetNode(G, i, e->ivex);
                    e->ilink = tempNode;
                    flag = 1;
                }
                tempNode = GetNode(G, i, e->jvex);
                e->jlink = tempNode;

                e = e->ilink;
            }
            //e = GetNode(G, i, e->jvex);    //處理最后一個
        }
        else
            G->adjList[i].firstedge = GetNode(G, i, i);
    }
}

int main()
{
    AMLGraphList gl;
    CreateAMLGraph(&gl);
    gl;
    system("pause");
    return 0;
}

七:圖的存儲結構(5)---邊集數組

邊集數組是由兩個一維數組構成。一個是存儲頂點的信息;另一個是存儲邊的信息。
這個邊數組每個數據元素由一條邊的起點下標(begin)、終點下標(end)和權(weight)組成。

結構

表現

如上圖所示,邊集數組關注的是邊的集合,在邊集數組中要查找一個頂點的度需要掃描整個邊數組,效率並不高。
因此它更適合對邊依次進行處理的操作,而不適合對頂點相關的操作。

 代碼實現

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MAXVEX 100    //最大頂點數

typedef char VertexType;    //頂點類型,字符型A,B,C,D...
typedef int EdgeType;    //邊上權值類型10,15,...

typedef struct VertexNode   //頂點表結點
{
    VertexType data;    //頂點域,存儲頂點信息
}VertexNode, VertexList[MAXVEX];

typedef struct EdgeNode   //邊集表結點
{
    int begin, end, weight;
}EdgeNode, EdgeList[MAXVEX];

typedef struct
{
    VertexList vexList;    //頂點表
    EdgeList edgeList;    //邊集表
    int numVertexes, numEdges;    //圖中所存儲的頂點數和邊數
}EdgeGraphList;


void CreateEdgeGraph(EdgeGraphList* G)
{
    int i, j ,k,w;
    printf("please input number of vertex and edge:\n");
    scanf("%d,%d",&G->numVertexes,&G->numEdges);    //輸入頂點數和邊數
    getchar();    //可以獲取回車符

    //獲取頂點數組信息
    for (i = 0; i < G->numVertexes;i++)    //輸入頂點信息
    {
        scanf("%c", &G->vexList[i].data);    //輸入頂點信息
    }

    //獲取邊數組
    for (k = 0; k < G->numEdges;k++)
    {
        printf("input edge(vi,vj) vertexs series and the weight:\n");
        scanf("%d,%d,%d", &i, &j,&w);
        getchar();
        //由於是無向圖,對稱矩陣,當我們設置邊以后,需要在兩個地方設置結點
        G->edgeList[k].begin = i;
        G->edgeList[k].end = j;
        G->edgeList[k].weight = w;
    }
}

int main()
{
    EdgeGraphList gl;
    CreateEdgeGraph(&gl);
    gl;
    system("pause");
    return 0;
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM