數(shù)據(jù)結(jié)構(gòu)學(xué)習(xí)筆記之圖

概念

圖的定義

圖(Graph)是由頂點(diǎn)的有窮非空集合和頂點(diǎn)之間的邊的集合組成满力,通常
表示為: G(V,E)作喘。其中厢蒜,G 表示一個(gè)圖霞势,V 是圖 G 中頂點(diǎn)的集合,E 是
圖 G 中邊的集合斑鸦。

需要注意:

  1. 圖中數(shù)據(jù)元素叫做頂點(diǎn)(Vertext)愕贡。

  2. 在圖中,不允許沒有頂點(diǎn)巷屿。若 V 是圖的頂點(diǎn)的集合固以,那么,V 是非空
    有窮集合嘱巾。

  3. 圖的任意兩個(gè)頂點(diǎn)之間都可能有關(guān)系憨琳,它們的關(guān)系用邊來表示诫钓。邊集可
    以是空的。

其他概念

無向邊

若頂點(diǎn) $V_i$ 到 $V_j$ 之間的邊沒有方向栽渴,這條邊就叫做無向邊(Edge),
用無序偶對 ($V_iV_j$) 來表示尖坤。

無向圖

如果圖中任意兩個(gè)頂點(diǎn)之間的邊都是無向邊稳懒,則稱該圖為無項(xiàng)圖(Undirected graphs)闲擦。

有向邊

若從頂點(diǎn) $V_i$ 到 $V_j$ 的邊有方向,則稱這條邊為有向邊场梆,也稱為弧 (Arc)墅冷。

這條有向邊用有序偶 $<V_i,V_j>來表示,$V_j是弧尾(Tail)或油,$V_j$是弧頭(Head)寞忿。

有向圖

如果圖中任意兩個(gè)頂點(diǎn)之間的邊都是有向邊,這個(gè)圖就是有向圖顶岸。

無向邊用小括號 “()”表示腔彰,有向邊用尖括號“<>”表示。

簡單圖

在圖中辖佣,若不存在頂點(diǎn)到其自身的邊霹抛,且同一條邊不重復(fù)出現(xiàn),這樣的圖就是簡單圖卷谈。

數(shù)據(jù)結(jié)構(gòu)_圖_簡單圖

無向完全圖

在無向圖中杯拐,如何任意兩點(diǎn)之間都存在邊,這個(gè)圖就是無向完全圖世蔗。

n 個(gè)頂點(diǎn)的無向完全圖有 ${n(n-1)} \over 2$ 條邊端逼。

有向完全圖

在有向圖中,如果任意兩點(diǎn)之間都存在方向互為相反的兩條弧污淋,這個(gè)圖就是有向完全圖顶滩。

n個(gè)頂點(diǎn)的有向完全圖有 $n(n-1) \over 2$ 條邊。

稠密圖和稀疏圖

邊或弧很少的圖是稀疏圖寸爆;邊或弧很多的圖是稠密圖礁鲁。

它們都是相對概念。

權(quán)而昨、網(wǎng)

與圖的邊或弧相關(guān)的數(shù)字叫做權(quán)(Weight)救氯。

權(quán)可以表示一個(gè)頂點(diǎn)到另一個(gè)頂點(diǎn)的距離或耗費(fèi)。

帶權(quán)的圖叫做網(wǎng)(Network)歌憨。

子圖

假設(shè)有兩個(gè)圖 $G = (V,\lbrace E \rbrace)$着憨,$G' = (V',\lbrace E' \rbrace)$,$V' \subseteq V$务嫡,$E' \subseteq E$甲抖,那么漆改,
G'G 的子圖。

圖的頂點(diǎn)與邊間的關(guān)系(暫時(shí)不做筆記准谚,有空再補(bǔ)充)

概念太多挫剑,記錄太麻煩,暫時(shí)不做筆記柱衔,有空再補(bǔ)充樊破。

連通圖

連通圖

圖7-2-13圖2根據(jù)定義,我認(rèn)為它不是強(qiáng)連通圖唆铐。

數(shù)據(jù)結(jié)構(gòu)_圖_連通圖
數(shù)據(jù)結(jié)構(gòu)_圖_連通圖_2
數(shù)據(jù)結(jié)構(gòu)_圖_連通圖_3
數(shù)據(jù)結(jié)構(gòu)_圖_連通圖_4

生成樹

不理解哲戚。

數(shù)據(jù)結(jié)構(gòu)_圖_生成樹_1
數(shù)據(jù)結(jié)構(gòu)_圖_生成樹_2

有向樹

不理解。

數(shù)據(jù)結(jié)構(gòu)_圖_有向樹_1
數(shù)據(jù)結(jié)構(gòu)_圖_有向樹_2

圖的抽象數(shù)據(jù)類型

ADT 圖(Graph)

Data
    頂點(diǎn)的有窮非空集合和邊的集合
    
Operation
    CreateGraph(*G, V, VR):按照頂點(diǎn)集 V 和 邊弧集 VR 的定義構(gòu)造圖 G艾岂。
    DestroyGraph(*G):圖G存在則銷毀它顺少。
    LocateVex(G, u):若圖 G 中存在頂點(diǎn) u,則返回它在圖中的位置王浴。
    GetVex(G, v):返回圖 G 中頂點(diǎn) v 的值脆炎。
    PutVex(G, v, value):將圖 G 中頂點(diǎn) v 賦值 value。
    FirstAdjVex(G, *v):返回頂點(diǎn) v 的一個(gè)鄰接頂點(diǎn)氓辣,若頂點(diǎn)在 G 中無鄰接頂點(diǎn)則返回空秒裕。
    NextAdjVex(G, v, *w):返回頂點(diǎn) v 相對于頂點(diǎn) w 的下一個(gè)鄰接頂點(diǎn),若 w 是 v 的最后
                          一個(gè)鄰接點(diǎn)則返回“空”筛婉。
    InsertVex(*G, v):在圖 G 中增添新頂點(diǎn) v簇爆。
    DeleteVex(*G, v): 刪除圖  G 中頂點(diǎn) v 及其相關(guān)的弧。
    InsertArc(*G, v, w):在圖中增添弧 <v,w>爽撒,若 G 是無向圖入蛆,還要增加對稱弧 <w,v>。
    DeleteArc(*G, v, w):在圖中刪除弧 <v,w>硕勿,若 G 是無向圖哨毁,還需要?jiǎng)h除對稱弧 <w,v>。
    DFSTraverse(G):對圖 G 深度優(yōu)先遍歷源武,在遍歷過程中對每個(gè)頂點(diǎn)調(diào)用扼褪。
    HFSTraverse(G):對圖 G 廣度優(yōu)先遍歷,在遍歷過程中對每個(gè)頂點(diǎn)調(diào)用粱栖。
endADT

圖的存儲(chǔ)結(jié)構(gòu)(難理解)

鄰接矩陣

定義

圖的鄰接矩陣(Adjacency Matrix)存儲(chǔ)方式是用兩個(gè)數(shù)組表示圖话浇。一個(gè)一維數(shù)組存儲(chǔ)圖中頂點(diǎn)信息,一個(gè)
二維數(shù)組(稱為鄰接矩陣)存儲(chǔ)圖中的邊或弧信息闹究。

數(shù)據(jù)結(jié)構(gòu)_圖_鄰接矩陣_定義
無向圖實(shí)例
數(shù)據(jù)結(jié)構(gòu)_圖_鄰接矩陣_解釋
有向圖實(shí)例
數(shù)據(jù)結(jié)構(gòu)_圖_鄰接矩陣_有向圖
網(wǎng)圖
數(shù)據(jù)結(jié)構(gòu)_圖_鄰接矩陣_網(wǎng)圖定義
數(shù)據(jù)結(jié)構(gòu)_圖_鄰接矩陣_網(wǎng)圖

鄰接矩陣存儲(chǔ)結(jié)構(gòu)

鄰接矩陣存儲(chǔ)結(jié)構(gòu)代碼:

備注:用65536代替 $\infty$

typedef char VertexType;
typedef int EdgeType;
#define MAXVEX 100;     // 最大頂點(diǎn)數(shù)
#define INFINITY 65535;  
typedef struct
{
    VertexType vexs[MAXVEX];    // 頂點(diǎn)表
    EdgeType arc[MAXVEX][MAXVEX];   // 鄰接矩陣幔崖,可看作邊表
    int numVertexes, numEdges;  // 圖中當(dāng)前頂點(diǎn)數(shù)和邊數(shù)
}MGraph;

創(chuàng)建無向網(wǎng)圖代碼:

void CreateGraph(MGraph *G)
{
    int i, j, k, w;
    printf("%s", "輸入頂點(diǎn)數(shù)和邊數(shù):\n");
    scanf("%d, %d", &G->numVertexes, &G->numEdges);     // 輸入頂點(diǎn)數(shù)和邊數(shù)
    for(i = 0; i < G->numVertexes; i++){
        scanf(&G->vexs[i]);
    }
    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("輸入邊(vi,vj)上的下標(biāo)i、下標(biāo)j和權(quán)w:\n");
        scanf("%d, %d, %d", &i, &j, &w);    // 輸入邊(vi,vj)上的權(quán)w
        G->arc[i][j] = w;
        G->arc[j][i] = G->arc[i][j];    // 因?yàn)槭菬o向圖赏寇,矩陣對稱
    }
}

鄰接表

概念

定義

數(shù)組與鏈表相結(jié)合的方法稱為鄰接表(Adjacency List)吉嫩。

思路
  1. 圖中頂點(diǎn)用一個(gè)一維數(shù)組存儲(chǔ)。該數(shù)組存儲(chǔ)兩部分內(nèi)容:頂點(diǎn)信息和指針嗅定。
    該指針指向該頂點(diǎn)的第一個(gè)鄰接點(diǎn)自娩。

  2. 圖中的每個(gè)頂點(diǎn) $v_i$ 的所有鄰接點(diǎn)構(gòu)成一個(gè)線性表,用單鏈表存儲(chǔ)渠退。
    這個(gè)線性表可能叫 邊表忙迁,也可能叫 出邊表

當(dāng)圖為無向圖的時(shí)候智什,這個(gè)線性表叫做頂點(diǎn) $v_i$ 的邊表动漾。

當(dāng)圖為有向圖的時(shí)候,這個(gè)線性表叫做頂點(diǎn) $v_i$ 作為弧尾的出邊表荠锭。

摘抄書本
無向圖的鄰接表結(jié)構(gòu)
數(shù)據(jù)結(jié)構(gòu)_圖_鄰接表_無向圖的鄰接表結(jié)構(gòu)

$v_0$ 的鄰接點(diǎn)是 $v_1,v_2晨川,v_3$证九,$v_0$的 firstEdge 存儲(chǔ)的指針指向它的第一個(gè)鄰接點(diǎn) $v_1$。
$v_1$ 的 adjvex 存儲(chǔ)的是 該頂點(diǎn)在頂點(diǎn)表中的下標(biāo)共虑,next 存儲(chǔ)的指針指向 $v_0$ 的第二個(gè)鄰接點(diǎn) $v_2$愧怜。

有向圖的鄰接表結(jié)構(gòu)
數(shù)據(jù)結(jié)構(gòu)_圖_鄰接表_有向圖的鄰接表結(jié)構(gòu)_1
數(shù)據(jù)結(jié)構(gòu)_圖_鄰接表_有向圖的鄰接表結(jié)構(gòu)_2
網(wǎng)圖的鄰接表結(jié)構(gòu)
數(shù)據(jù)結(jié)構(gòu)_圖_鄰接表_網(wǎng)圖

鄰接表存儲(chǔ)結(jié)構(gòu)(看不懂)

結(jié)點(diǎn)定義代碼

typedef char VertexType;
typedef int EdgeType;

typedef struct EdgeNode     // 邊表結(jié)點(diǎn)
{
    int adjvex;     // 鄰接點(diǎn)域,存儲(chǔ)該頂點(diǎn)對應(yīng)的下標(biāo)
    EdgeType weight;    // 權(quán)值
    struct EdgeNode *next;  // 鏈域妈拌,指向下一個(gè)連接點(diǎn)
}EdgeNode;

typedef struct VertexNode   // 頂點(diǎn)表結(jié)點(diǎn)
{
    VertexType data;    // 頂點(diǎn)域拥坛,存儲(chǔ)頂點(diǎn)信息
    EdgeNode *firstEdge;    // 邊表頭指針
}VertexNode, AdjList[MAXVEX];

typedef struct
{
    AdjList adjList;
    int numVertexes, numEdges;      // 圖中當(dāng)前頂點(diǎn)數(shù)和邊數(shù)
}GraphAdjList;

邊表結(jié)點(diǎn) EdgeNode 為什么如此定義?

無向圖的鄰接表創(chuàng)建代碼

void CreateALGraph(GraphAdjList *G)
{
    int i, j, k;
    EdgeNode *e;
    printf("輸入頂點(diǎn)數(shù)和邊數(shù):\n");
    scanf("%d, %d", &G->numVertexes, &G->numEdges);     // 輸入頂點(diǎn)數(shù)和邊數(shù) 
    
    for(i = 0; i < G->numVertexes; i++){
        scanf(&G->adjList[i].data);     // 輸入頂點(diǎn)信息尘分。這種寫法猜惋,有問題嗎?
        G->adjList[i].firstEdge = NULL;     // 將邊表置為空表培愁。為什么著摔?
    }
    
    for(k = 0; k < G->numVertexes; i++){    // 建立邊表
        printf("輸入邊(Vi,Vj)上的頂點(diǎn)序號:\n");
        scanf("%d, %d", &i, &j);    // 輸入邊(Vi,Vj)上的頂點(diǎn)序號
        e = (EdgeNode *)malloc(sizeof(EdgeNode));       // 申請內(nèi)存空間,創(chuàng)建邊表結(jié)點(diǎn)
        e->adjvex = j;      // 鄰接序號為j
        e->next = G->adjList[i].firstEdge;  // 將e指針指向當(dāng)前頂點(diǎn)指向的結(jié)點(diǎn) 定续?
        G->adjList[i].firstEdge = e;    // 將當(dāng)前頂點(diǎn)的指針指向e
        e = (EdgeNode *)malloc(sizeof(EdgeNode));   // 申請內(nèi)存空間谍咆,創(chuàng)建邊表結(jié)點(diǎn)
        e->adjvex = i;  // 鄰接序號為i
        e->next = G->adjList[j].firstEdge;  // 將e指針指向當(dāng)前頂點(diǎn)指向的結(jié)點(diǎn)
        G->adjList[j].firstEdge = e;    // 將當(dāng)前頂點(diǎn)的指針指向e
    }
}

十字鏈表(看不懂)

摘抄

數(shù)據(jù)結(jié)構(gòu)_圖_十字鏈表_1

數(shù)據(jù)結(jié)構(gòu)_圖_十字鏈表_2

數(shù)據(jù)結(jié)構(gòu)_圖_十字鏈表_3

數(shù)據(jù)結(jié)構(gòu)_圖_十字鏈表_4

鄰接多重表(看不懂)

摘抄

數(shù)據(jù)結(jié)構(gòu)_圖_鄰接多重表_1

數(shù)據(jù)結(jié)構(gòu)_圖_鄰接多重表_2

數(shù)據(jù)結(jié)構(gòu)_圖_鄰接多重表_3

數(shù)據(jù)結(jié)構(gòu)_圖_鄰接多重表_4

數(shù)據(jù)結(jié)構(gòu)_圖_鄰接多重表_5

邊集數(shù)組

摘抄

數(shù)據(jù)結(jié)構(gòu)_圖_邊集數(shù)組_1

數(shù)據(jù)結(jié)構(gòu)_圖_邊集數(shù)組_2

圖的遍歷

定義

從圖中某一個(gè)頂點(diǎn)出發(fā)遍訪圖的其余所有頂點(diǎn),且使所有頂點(diǎn)被訪問且只訪問一次私股。
這個(gè)過程摹察,就叫做圖的遍歷(Traversing Graph)。

深度優(yōu)先遍歷(Depth_First_Search)

摘抄

數(shù)據(jù)結(jié)構(gòu)_圖_深度優(yōu)先遍歷_摘抄_1

虛線表示已經(jīng)遍歷過的點(diǎn)倡鲸,實(shí)線表示未遍歷過的點(diǎn)供嚎。

數(shù)據(jù)結(jié)構(gòu)_圖_深度優(yōu)先遍歷_摘抄_2

數(shù)據(jù)結(jié)構(gòu)_圖_深度優(yōu)先遍歷_摘抄_3

代碼

鄰接矩陣代碼
typedef int Boolean;    // Boolean是布爾類型,其值是TRUE或FALSE
Boolean visited[MAX];   // 訪問標(biāo)志的數(shù)組

void DFS(MGraph G, int i)
{
    int j;
    visited[i] = TRUE;
    printf("%c", G.vexs[i]);
    
    /*2*/for(j = 0; j < G.numVertexes; j++){
        /*1*/if(G.arc[i][j] == 1 && !visited[j] ){
            DFS(G, j);  // 對未訪問的頂點(diǎn)遞歸調(diào)用
        }
    }
}

void DFSTraverse(MGraph G)
{
    int i;
    
    for(i = 0; i < G.numVertexes; i++){
        visited[i] = FALSE;     // 初始所有頂點(diǎn)狀態(tài)都是未訪問過狀態(tài)
    }
    
    for(i = 0; i < G.numVertexes; i++){
        if(!visited[i]){
            DFS(G, i);
        }
    }
}

第1行,G.arc[i][j] == 1 表明 $v_iv_j$ 邊存在查坪,這是根據(jù)鄰接圖矩陣定義得出的
結(jié)果寸宏。

第1行,visited[j] 不能理解這句偿曙。

第2行的循環(huán)里面的遞歸氮凝,什么時(shí)候終止?

鄰接表代碼(不懂)
void DFS(GraphAdjList GL, int i)
{
    EdgeNode *p;
    visited[i] = TRUE;
    printf("%c", GL->adjList[i].data);
    p = GL->adjList[i].firstEdge;
    while(p){
        if(!visited[p->adjvex]){
            DFS(GL, p->adjvex);
        }
        p = p->next;
    }
}

void DFSTraverse(GraphAdjList GL)
{
    int i;
    for(i = 0; i < GL->numVertexes; i++){
        visited[i] = FALSE;
    }
    for(i = 0; i < GL->numVertexes; i++){
        if(!visited[i]){
            DFS(GL, i);
        }
    }
}

廣度優(yōu)先遍歷(Breadth_First_Search)

摘抄

數(shù)據(jù)結(jié)構(gòu)_圖_廣度優(yōu)先遍歷_摘抄_1
數(shù)據(jù)結(jié)構(gòu)_圖_廣度優(yōu)先遍歷_摘抄_2

不明白如何得到這張圖望忆。

代碼

鄰接矩陣代碼(不懂)
void BFSTraverse(MGraph G)
{
    int i, j;
    Queue Q;
    for(i = 0; i < G.numVertexes; i++){
        visited[i] = FALSE;
    }
    InitQueue(&Q);  // 初始化一個(gè)輔助用的隊(duì)列
    for(i = 0; i < G.numVertexes; i++){     // 對每一個(gè)頂點(diǎn)做循環(huán)
        if(!visited[i]){
            visited[i] = TRUE;
            printf("%c", G.vexs[i]);
            EnQueue(&Q, i);     // 將此頂點(diǎn)入隊(duì)列
            while(!QueueEmpty(Q)){
                DeQueue(&Q, &i);    // 將隊(duì)列中元素出隊(duì)列罩阵,賦值給i
                for(j = 0; j < G.numVertexes; j++){
                    if(G.arc[i][j] == 1 && !visited[j]){
                        visited[j] = TRUE;
                        printf("%c", G.vexs[j]);
                        EnQueue(&Q, j);
                    }
                }
            }
        }
    }
}
鄰接表代碼(不懂)
void BFSTraverse(GraphAdjList GL)
{
    int i;
    EdgeNode *p;
    Queue Q;
    for(i = 0; i < GL->numVertexes; i++){
        visited[i] = FALSE;
    }
    InitQueue(&Q);
    for(i = 0; i < GL->numVertexes; i++){
        if(!visited[i]){
            visited[i] = TRUE;
            printf("%c", GL->adjList[i].data);
            EnQueue(&Q, i);
            while(!QueueEmpty(Q)){
                DeQueue(&Q, &i);
                p = GL->adjList[i].firstEdge;   // 找到當(dāng)前頂點(diǎn)邊表鏈表頭指針
                while(p){
                    if(!visited[p->adjvex]){
                        visited[p->adjvex] = TRUE;
                        printf("%c", GL->adjList[p->adjvex].data);
                        EnQueue(&Q, p->adjvex);
                    }
                }
                p = p->next;    // 指針指向下一個(gè)鄰接點(diǎn)
            }
        }
    }
}

最小生成樹

定義(不懂)

把構(gòu)造連通網(wǎng)的最小代價(jià)生成樹稱為最小生成樹(Minimum Cost Spanning Tree)。

普里姆(Prim)算法(不懂)

代碼

void MiniSpanTree_Prim(MGraph G)
{
    int min, i, j, k;
    int adjvex[MAXVEX];     // 保存相關(guān)頂點(diǎn)下標(biāo)
    int lowcost[MAXVEX];    // 保存相關(guān)頂點(diǎn)間邊的權(quán)值
    // 初始化第一個(gè)權(quán)值為0启摄,即v0加入生成樹
    // lowcost的值為0稿壁,在這里就是此下標(biāo)的頂點(diǎn)已經(jīng)加入生成樹
    lowcost[0] = 0;     
    adjvex[0] = 0;  // 初始化第一個(gè)頂點(diǎn)下標(biāo)為0
    for(i = 1; i < G.numVertexes; i++){
        lowcost[i] = G.arc[0][i];   // 將v0頂點(diǎn)與之有邊的權(quán)值存入數(shù)組
        adjvex[i] = 0;  // 初始化都為v0的下標(biāo)
    }
    for(i = 1; i < G.numVertexes; i++){
        min = INFINITY; //  初始化最小權(quán)值為 INFINITY
        j = 1; k = 0;
        while(j < G.numVertexes){
            if(lowcost[j] != 0 && lowcost[j] < min){
                min = lowcost[j];   // 讓當(dāng)前權(quán)值成為最小值
                k = j;      // 將當(dāng)前最小值的下標(biāo)存入k
            }
            j++;
        }
        printf("(%d, %d)", adjvex[k], k);   //打印當(dāng)前頂點(diǎn)邊中權(quán)值最小的邊
        lowcost[k] = 0;     // 將當(dāng)前頂點(diǎn)的權(quán)值設(shè)置為0,表示此頂點(diǎn)已經(jīng)完成任務(wù)
        for(j = 1; j < G.numVertexes; j++){
            if(lowcost[j] != 0 && G.arc[k][j] < lowcost[j]){
                lowcost[j] = G.arc[k][j];   // 將較小權(quán)值存入lowcost
                adjvex[j] = k;      // 將下標(biāo)為k的頂點(diǎn)存入adjvex
            }
        }
    }
}

代碼解釋

數(shù)據(jù)結(jié)構(gòu)_圖_普里姆算法_代碼解釋_8

數(shù)據(jù)結(jié)構(gòu)_圖_普里姆算法_代碼解釋_1

數(shù)據(jù)結(jié)構(gòu)_圖_普里姆算法_代碼解釋_2

數(shù)據(jù)結(jié)構(gòu)_圖_普里姆算法_代碼解釋_3

數(shù)據(jù)結(jié)構(gòu)_圖_普里姆算法_代碼解釋_4

數(shù)據(jù)結(jié)構(gòu)_圖_普里姆算法_代碼解釋_5

數(shù)據(jù)結(jié)構(gòu)_圖_普里姆算法_代碼解釋_6

數(shù)據(jù)結(jié)構(gòu)_圖_普里姆算法_代碼解釋_7

克魯斯卡爾(Kruskal)算法

代碼

typedef struct 
{
    int begin;
    int end;
    int weight;
}Edge;

void MiniSpanTree_Kruskal(MGraph G)
{
    int i, n, m;
    Edge edges[MAXEDGE];    // 定義邊集數(shù)組
    int parent[MAXVEX];     // 定義一數(shù)組用來判斷邊與邊是否形成環(huán)路
    for(i = 0; i < G.numVertexes; i++){
        parent[i] = 0;      // 初始化數(shù)組值為0
    }
    for(i = 0; i < G.numVertexes; i++){
        n = Find(parent, edges[i].begin);
        m = Find(parent, edges[i].end);
        if(n != m){     // 假如n與m不等歉备,說明此邊沒有與現(xiàn)有生成樹形成環(huán)路
            // 將此邊的結(jié)尾頂點(diǎn)放入下標(biāo)為起點(diǎn)的parent中
            // 表示此頂點(diǎn)已經(jīng)在生成樹集合中
            parent[n] = m;      
            printf("(%d, %d) %d", edges[i].begin, edges[i].end, edges[i].weight);
        }
    }
}

int Find(int *parent, int f)    // 查找連線頂點(diǎn)的尾部下標(biāo)
{
    while(parent[f] > 0){
        f = parent[f];
    }
    
    return f;
}

代碼解釋

數(shù)據(jù)結(jié)構(gòu)_圖_克魯斯卡爾算法_代碼解釋_1

數(shù)據(jù)結(jié)構(gòu)_圖_克魯斯卡爾算法_代碼解釋_2

數(shù)據(jù)結(jié)構(gòu)_圖_克魯斯卡爾算法_代碼解釋_3

數(shù)據(jù)結(jié)構(gòu)_圖_克魯斯卡爾算法_代碼解釋_4

數(shù)據(jù)結(jié)構(gòu)_圖_克魯斯卡爾算法_代碼解釋_5

數(shù)據(jù)結(jié)構(gòu)_圖_克魯斯卡爾算法_代碼解釋_6

數(shù)據(jù)結(jié)構(gòu)_圖_克魯斯卡爾算法_代碼解釋_7

數(shù)據(jù)結(jié)構(gòu)_圖_克魯斯卡爾算法_代碼解釋_8

數(shù)據(jù)結(jié)構(gòu)_圖_克魯斯卡爾算法_代碼解釋_9

數(shù)據(jù)結(jié)構(gòu)_圖_克魯斯卡爾算法_代碼解釋_10

數(shù)據(jù)結(jié)構(gòu)_圖_克魯斯卡爾算法_代碼解釋_11

數(shù)據(jù)結(jié)構(gòu)_圖_克魯斯卡爾算法_代碼解釋_12

最短路徑(看不懂)

暫時(shí)放棄

定義

非網(wǎng)圖的最短路徑傅是,是指兩頂點(diǎn)之間經(jīng)過的邊數(shù)最少的路徑。

網(wǎng)圖的最短路徑蕾羊,是指兩頂點(diǎn)之間經(jīng)過的邊上的權(quán)值之和最小的路徑喧笔。
路徑上的第一個(gè)源點(diǎn),最后一個(gè)頂點(diǎn)是終點(diǎn)。

拓?fù)渑判?/h2>

關(guān)鍵路徑

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市啡捶,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌浆劲,老刑警劉巖,帶你破解...
    沈念sama閱讀 221,635評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件哀澈,死亡現(xiàn)場離奇詭異牌借,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)日丹,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,543評論 3 399
  • 文/潘曉璐 我一進(jìn)店門走哺,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人哲虾,你說我怎么就攤上這事丙躏。” “怎么了束凑?”我有些...
    開封第一講書人閱讀 168,083評論 0 360
  • 文/不壞的土叔 我叫張陵晒旅,是天一觀的道長。 經(jīng)常有香客問我汪诉,道長废恋,這世上最難降的妖魔是什么谈秫? 我笑而不...
    開封第一講書人閱讀 59,640評論 1 296
  • 正文 為了忘掉前任,我火速辦了婚禮鱼鼓,結(jié)果婚禮上拟烫,老公的妹妹穿的比我還像新娘。我一直安慰自己迄本,他們只是感情好硕淑,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,640評論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著嘉赎,像睡著了一般置媳。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上公条,一...
    開封第一講書人閱讀 52,262評論 1 308
  • 那天拇囊,我揣著相機(jī)與錄音,去河邊找鬼靶橱。 笑死寥袭,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的抓韩。 我是一名探鬼主播纠永,決...
    沈念sama閱讀 40,833評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼谒拴!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起涉波,我...
    開封第一講書人閱讀 39,736評論 0 276
  • 序言:老撾萬榮一對情侶失蹤英上,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后啤覆,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體苍日,經(jīng)...
    沈念sama閱讀 46,280評論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,369評論 3 340
  • 正文 我和宋清朗相戀三年窗声,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了相恃。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,503評論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡笨觅,死狀恐怖拦耐,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情见剩,我是刑警寧澤杀糯,帶...
    沈念sama閱讀 36,185評論 5 350
  • 正文 年R本政府宣布,位于F島的核電站苍苞,受9級特大地震影響固翰,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,870評論 3 333
  • 文/蒙蒙 一骂际、第九天 我趴在偏房一處隱蔽的房頂上張望疗琉。 院中可真熱鬧,春花似錦歉铝、人聲如沸盈简。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,340評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽送火。三九已至,卻和暖如春先匪,著一層夾襖步出監(jiān)牢的瞬間种吸,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,460評論 1 272
  • 我被黑心中介騙來泰國打工呀非, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留坚俗,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,909評論 3 376
  • 正文 我出身青樓岸裙,卻偏偏與公主長得像猖败,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子降允,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,512評論 2 359

推薦閱讀更多精彩內(nèi)容