日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

数据结构--图(Graph)详解(三)

發(fā)布時(shí)間:2024/4/11 编程问答 41 豆豆
生活随笔 收集整理的這篇文章主要介紹了 数据结构--图(Graph)详解(三) 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

數(shù)據(jù)結(jié)構(gòu)–圖(Graph)詳解(三)

文章目錄

  • 數(shù)據(jù)結(jié)構(gòu)--圖(Graph)詳解(三)
    • 一、深度優(yōu)先生成樹和廣度優(yōu)先生成樹
      • 1.鋪墊
      • 2.非連通圖的生成森林
      • 3.深度優(yōu)先生成森林
      • 4.廣度優(yōu)先生成森林
    • 二、幾個(gè)特別NB的算法詳解
      • 1.普里姆算法(Prim算法)求最小生成樹
      • 2.克魯斯卡爾算法(Kruskal算法)求最小生成樹
      • 3.拓?fù)渑判蛩惴?/li>
      • 4.迪杰斯特拉(Dijkstra算法)算法
      • 5.弗洛伊德算法

一、深度優(yōu)先生成樹和廣度優(yōu)先生成樹

1.鋪墊

本博客來解決對(duì)于給定的無向圖,如何構(gòu)建它們相對(duì)應(yīng)的生成樹或者生成森林。

  • 其實(shí)在對(duì)無向圖進(jìn)行遍歷的時(shí)候,遍歷過程中所經(jīng)歷過的圖中的頂點(diǎn)和邊的組合,就是圖的生成樹或者生成森林。


例如,圖 1 中的無向圖是由 V1~V7 的頂點(diǎn)和編號(hào)分別為 a~i 的邊組成。

當(dāng)使用深度優(yōu)先搜索算法時(shí),假設(shè) V1 作為遍歷的起始點(diǎn),涉及到的頂點(diǎn)和邊的遍歷順序?yàn)?#xff08;不唯一):

此種遍歷順序構(gòu)建的生成樹為:

  • 由深度優(yōu)先搜索得到的樹為深度優(yōu)先生成樹。
  • 同理,廣度優(yōu)先搜索生成的樹為廣度優(yōu)先生成樹

圖 1 無向圖以頂點(diǎn) V1 為起始點(diǎn)進(jìn)行廣度優(yōu)先搜索遍歷得到的樹,如圖 3 所示:

2.非連通圖的生成森林

  • 非連通圖在進(jìn)行遍歷時(shí),實(shí)則是對(duì)非連通圖中每個(gè)連通分量分別進(jìn)行遍歷,在遍歷過程經(jīng)過的每個(gè)頂點(diǎn)和邊,就構(gòu)成了每個(gè)連通分量的生成樹。
  • 非連通圖中,多個(gè)連通分量構(gòu)成的多個(gè)生成樹為非連通圖的生成森林。

3.深度優(yōu)先生成森林


例如,對(duì)圖 4 中的非連通圖 (a) 采用深度優(yōu)先搜索算法遍歷時(shí),得到的深度優(yōu)先生成森林(由 3 個(gè)深度優(yōu)先生成樹構(gòu)成)如 (b) 所示(不唯一)。

非連通圖在遍歷生成森林時(shí),可以采用孩子兄弟表示法將森林轉(zhuǎn)化為一整棵二叉樹進(jìn)行存儲(chǔ)。

  • 具體實(shí)現(xiàn)的代碼:
#include <stdio.h> #include <stdlib.h> #define MAX_VERtEX_NUM 20 //頂點(diǎn)的最大個(gè)數(shù) #define VRType int //表示頂點(diǎn)之間的關(guān)系的變量類型 #define VertexType int //圖中頂點(diǎn)的數(shù)據(jù)類型 typedef enum{false,true}bool; //定義bool型常量 bool visited[MAX_VERtEX_NUM]; //設(shè)置全局?jǐn)?shù)組,記錄標(biāo)記頂點(diǎn)是否被訪問過typedef struct {VRType adj; //對(duì)于無權(quán)圖,用 1 或 0 表示是否相鄰;對(duì)于帶權(quán)圖,直接為權(quán)值。 }ArcCell,AdjMatrix[MAX_VERtEX_NUM][MAX_VERtEX_NUM];typedef struct {VertexType vexs[MAX_VERtEX_NUM]; //存儲(chǔ)圖中頂點(diǎn)數(shù)據(jù)AdjMatrix arcs; //二維數(shù)組,記錄頂點(diǎn)之間的關(guān)系int vexnum,arcnum; //記錄圖的頂點(diǎn)數(shù)和弧(邊)數(shù) }MGraph;//孩子兄弟表示法的鏈表結(jié)點(diǎn)結(jié)構(gòu) typedef struct CSNode{VertexType data;struct CSNode * lchild;//孩子結(jié)點(diǎn)struct CSNode * nextsibling;//兄弟結(jié)點(diǎn) }*CSTree,CSNode;//根據(jù)頂點(diǎn)本身數(shù)據(jù),判斷出頂點(diǎn)在二維數(shù)組中的位置 int LocateVex(MGraph G,VertexType v){int i=0;//遍歷一維數(shù)組,找到變量vfor (; i<G.vexnum; i++) {if (G.vexs[i]==v) {break;}}//如果找不到,輸出提示語句,返回-1if (i>G.vexnum) {printf("no such vertex.\n");return -1;}return i; }//構(gòu)造無向圖 void CreateDN(MGraph *G){scanf("%d,%d",&(G->vexnum),&(G->arcnum));getchar();for (int i=0; i<G->vexnum; i++) {scanf("%d",&(G->vexs[i]));}for (int i=0; i<G->vexnum; i++) {for (int j=0; j<G->vexnum; j++) {G->arcs[i][j].adj=0;}}for (int i=0; i<G->arcnum; i++) {int v1,v2;scanf("%d,%d",&v1,&v2);int n=LocateVex(*G, v1);int m=LocateVex(*G, v2);if (m==-1 ||n==-1) {printf("no this vertex\n");return;}G->arcs[n][m].adj=1;G->arcs[m][n].adj=1;//無向圖的二階矩陣沿主對(duì)角線對(duì)稱} }int FirstAdjVex(MGraph G,int v) {//查找與數(shù)組下標(biāo)為v的頂點(diǎn)之間有邊的頂點(diǎn),返回它在數(shù)組中的下標(biāo)for(int i = 0; i<G.vexnum; i++){if( G.arcs[v][i].adj ){return i;}}return -1; }int NextAdjVex(MGraph G,int v,int w) {//從前一個(gè)訪問位置w的下一個(gè)位置開始,查找之間有邊的頂點(diǎn)for(int i = w+1; i<G.vexnum; i++){if(G.arcs[v][i].adj){return i;}}return -1; }void DFSTree(MGraph G,int v,CSTree*T){//將正在訪問的該頂點(diǎn)的標(biāo)志位設(shè)為truevisited[v]=true;bool first=true;CSTree q=NULL;//依次遍歷該頂點(diǎn)的所有鄰接點(diǎn)for (int w=FirstAdjVex(G, v); w>=0; w=NextAdjVex(G, v, w)) {//如果該臨界點(diǎn)標(biāo)志位為false,說明還未訪問if (!visited[w]) {//為該鄰接點(diǎn)初始化為結(jié)點(diǎn)CSTree p=(CSTree)malloc(sizeof(CSNode));p->data=G.vexs[w];p->lchild=NULL;p->nextsibling=NULL;//該結(jié)點(diǎn)的第一個(gè)鄰接點(diǎn)作為孩子結(jié)點(diǎn),其它鄰接點(diǎn)作為孩子結(jié)點(diǎn)的兄弟結(jié)點(diǎn)if (first) {(*T)->lchild=p;first=false;}//否則,為兄弟結(jié)點(diǎn)else{q->nextsibling=p;}q=p;//以當(dāng)前訪問的頂點(diǎn)為樹根,繼續(xù)訪問其鄰接點(diǎn)DFSTree(G, w, &q);}} }//深度優(yōu)先搜索生成森林并轉(zhuǎn)化為二叉樹 void DFSForest(MGraph G,CSTree *T){(*T)=NULL;//每個(gè)頂點(diǎn)的標(biāo)記為初始化為falsefor (int v=0; v<G.vexnum; v++) {visited[v]=false;}CSTree q=NULL;//遍歷每個(gè)頂點(diǎn)作為初始點(diǎn),建立深度優(yōu)先生成樹for (int v=0; v<G.vexnum; v++) {//如果該頂點(diǎn)的標(biāo)記位為false,證明未訪問過if (!(visited[v])) {//新建一個(gè)結(jié)點(diǎn),表示該頂點(diǎn)CSTree p=(CSTree)malloc(sizeof(CSNode));p->data=G.vexs[v];p->lchild=NULL;p->nextsibling=NULL;//如果樹未空,則該頂點(diǎn)作為樹的樹根if (!(*T)) {(*T)=p; }//該頂點(diǎn)作為樹根的兄弟結(jié)點(diǎn)else{q->nextsibling=p;}//每次都要把q指針指向新的結(jié)點(diǎn),為下次添加結(jié)點(diǎn)做鋪墊q=p;//以該結(jié)點(diǎn)為起始點(diǎn),構(gòu)建深度優(yōu)先生成樹DFSTree(G,v,&p);}} }//前序遍歷二叉樹 void PreOrderTraverse(CSTree T){if (T) {printf("%d ",T->data);PreOrderTraverse(T->lchild);PreOrderTraverse(T->nextsibling);}return; }int main() {MGraph G;//建立一個(gè)圖的變量CreateDN(&G);//初始化圖CSTree T;DFSForest(G, &T);PreOrderTraverse(T);return 0; }


圖中,3 種顏色的樹各代表一棵深度優(yōu)先生成樹,使用孩子兄弟表示法表示,也就是將三棵樹的樹根相連,第一棵樹的樹根作為整棵樹的樹根。

4.廣度優(yōu)先生成森林

  • 非連通圖采用廣度優(yōu)先搜索算法進(jìn)行遍歷時(shí),經(jīng)過的頂點(diǎn)以及邊的集合為該圖的廣度優(yōu)先生成森林。

拿圖 4(a)中的非連通圖為例,通過廣度優(yōu)先搜索得到的廣度優(yōu)先生成森林用孩子兄弟表示法為:

  • 實(shí)現(xiàn)代碼為:
#include <stdio.h> #include <stdlib.h> #define MAX_VERtEX_NUM 20 //頂點(diǎn)的最大個(gè)數(shù) #define VRType int //表示頂點(diǎn)之間的關(guān)系的變量類型 #define InfoType char //存儲(chǔ)弧或者邊額外信息的指針變量類型 #define VertexType int //圖中頂點(diǎn)的數(shù)據(jù)類型typedef enum{false,true}bool; //定義bool型常量bool visited[MAX_VERtEX_NUM]; //設(shè)置全局?jǐn)?shù)組,記錄標(biāo)記頂點(diǎn)是否被訪問過typedef struct {VRType adj; //對(duì)于無權(quán)圖,用 1 或 0 表示是否相鄰;對(duì)于帶權(quán)圖,直接為權(quán)值。InfoType * info; //弧或邊額外含有的信息指針 }ArcCell,AdjMatrix[MAX_VERtEX_NUM][MAX_VERtEX_NUM];typedef struct {VertexType vexs[MAX_VERtEX_NUM]; //存儲(chǔ)圖中頂點(diǎn)數(shù)據(jù)AdjMatrix arcs; //二維數(shù)組,記錄頂點(diǎn)之間的關(guān)系int vexnum,arcnum; //記錄圖的頂點(diǎn)數(shù)和弧(邊)數(shù) }MGraph;typedef struct CSNode{VertexType data;struct CSNode * lchild;//孩子結(jié)點(diǎn)struct CSNode * nextsibling;//兄弟結(jié)點(diǎn) }*CSTree,CSNode;typedef struct Queue{CSTree data;//隊(duì)列中存放的為樹結(jié)點(diǎn)struct Queue * next; }Queue;//根據(jù)頂點(diǎn)本身數(shù)據(jù),判斷出頂點(diǎn)在二維數(shù)組中的位置 int LocateVex(MGraph * G,VertexType v){int i=0;//遍歷一維數(shù)組,找到變量vfor (; i<G->vexnum; i++) {if (G->vexs[i]==v) {break;}}//如果找不到,輸出提示語句,返回-1if (i>G->vexnum) {printf("no such vertex.\n");return -1;}return i; }//構(gòu)造無向圖 void CreateDN(MGraph *G){scanf("%d,%d",&(G->vexnum),&(G->arcnum));for (int i=0; i<G->vexnum; i++) {scanf("%d",&(G->vexs[i]));}for (int i=0; i<G->vexnum; i++) {for (int j=0; j<G->vexnum; j++) {G->arcs[i][j].adj=0;G->arcs[i][j].info=NULL;}}for (int i=0; i<G->arcnum; i++) {int v1,v2;scanf("%d,%d",&v1,&v2);int n=LocateVex(G, v1);int m=LocateVex(G, v2);if (m==-1 ||n==-1) {printf("no this vertex\n");return;}G->arcs[n][m].adj=1;G->arcs[m][n].adj=1;//無向圖的二階矩陣沿主對(duì)角線對(duì)稱} }int FirstAdjVex(MGraph G,int v) {//查找與數(shù)組下標(biāo)為v的頂點(diǎn)之間有邊的頂點(diǎn),返回它在數(shù)組中的下標(biāo)for(int i = 0; i<G.vexnum; i++){if( G.arcs[v][i].adj ){return i;}}return -1; }int NextAdjVex(MGraph G,int v,int w) {//從前一個(gè)訪問位置w的下一個(gè)位置開始,查找之間有邊的頂點(diǎn)for(int i = w+1; i<G.vexnum; i++){if(G.arcs[v][i].adj){return i;}}return -1; }//初始化隊(duì)列 void InitQueue(Queue ** Q){(*Q)=(Queue*)malloc(sizeof(Queue));(*Q)->next=NULL; }//結(jié)點(diǎn)v進(jìn)隊(duì)列 void EnQueue(Queue **Q,CSTree T){Queue * element=(Queue*)malloc(sizeof(Queue));element->data=T;element->next=NULL;Queue * temp=(*Q);while (temp->next!=NULL) {temp=temp->next;}temp->next=element; }//隊(duì)頭元素出隊(duì)列 void DeQueue(Queue **Q,CSTree *u){(*u)=(*Q)->next->data;(*Q)->next=(*Q)->next->next; }//判斷隊(duì)列是否為空 bool QueueEmpty(Queue *Q){if (Q->next==NULL) {return true;}return false; }void BFSTree(MGraph G,int v,CSTree*T){CSTree q=NULL;Queue * Q;InitQueue(&Q);//根結(jié)點(diǎn)入隊(duì)EnQueue(&Q, (*T));//當(dāng)隊(duì)列為空時(shí),證明遍歷完成while (!QueueEmpty(Q)) {bool first=true;//隊(duì)列首個(gè)結(jié)點(diǎn)出隊(duì)DeQueue(&Q,&q);//判斷結(jié)點(diǎn)中的數(shù)據(jù)在數(shù)組中的具體位置int v=LocateVex(&G,q->data);//已經(jīng)訪問過的更改其標(biāo)志位visited[v]=true;//遍歷以出隊(duì)結(jié)點(diǎn)為起始點(diǎn)的所有鄰接點(diǎn)for (int w=FirstAdjVex(G,v); w>=0; w=NextAdjVex(G,v, w)) {//標(biāo)志位為false,證明未遍歷過if (!visited[w]) {//新建一個(gè)結(jié)點(diǎn) p,存放當(dāng)前遍歷的頂點(diǎn)CSTree p=(CSTree)malloc(sizeof(CSNode));p->data=G.vexs[w];p->lchild=NULL;p->nextsibling=NULL;//當(dāng)前結(jié)點(diǎn)入隊(duì)EnQueue(&Q, p);//更改標(biāo)志位visited[w]=true;//如果是出隊(duì)頂點(diǎn)的第一個(gè)鄰接點(diǎn),設(shè)置p結(jié)點(diǎn)為其左孩子if (first) {q->lchild=p;first=false;}//否則設(shè)置其為兄弟結(jié)點(diǎn)else{q->nextsibling=p;}q=p;}}} }//廣度優(yōu)先搜索生成森林并轉(zhuǎn)化為二叉樹 void BFSForest(MGraph G,CSTree *T){(*T)=NULL;//每個(gè)頂點(diǎn)的標(biāo)記為初始化為falsefor (int v=0; v<G.vexnum; v++) {visited[v]=false;}CSTree q=NULL;//遍歷圖中所有的頂點(diǎn)for (int v=0; v<G.vexnum; v++) {//如果該頂點(diǎn)的標(biāo)記位為false,證明未訪問過if (!(visited[v])) {//新建一個(gè)結(jié)點(diǎn),表示該頂點(diǎn)CSTree p=(CSTree)malloc(sizeof(CSNode));p->data=G.vexs[v];p->lchild=NULL;p->nextsibling=NULL;//如果樹未空,則該頂點(diǎn)作為樹的樹根if (!(*T)) {(*T)=p;}//該頂點(diǎn)作為樹根的兄弟結(jié)點(diǎn)else{q->nextsibling=p;}//每次都要把q指針指向新的結(jié)點(diǎn),為下次添加結(jié)點(diǎn)做鋪墊q=p;//以該結(jié)點(diǎn)為起始點(diǎn),構(gòu)建廣度優(yōu)先生成樹BFSTree(G,v,&p);}} }//前序遍歷二叉樹 void PreOrderTraverse(CSTree T){if (T) {printf("%d ",T->data);PreOrderTraverse(T->lchild);PreOrderTraverse(T->nextsibling);}return; }int main() {MGraph G;//建立一個(gè)圖的變量CreateDN(&G);//初始化圖CSTree T;BFSForest(G, &T);PreOrderTraverse(T);return 0; }

二、幾個(gè)特別NB的算法詳解

1.普里姆算法(Prim算法)求最小生成樹

通過前面的學(xué)習(xí),對(duì)于含有 n 個(gè)頂點(diǎn)的連通圖來說可能包含有多種生成樹,例如圖 1 所示:

圖 1 中的連通圖和它相對(duì)應(yīng)的生成樹,可以用于解決實(shí)際生活中的問題:

假設(shè)A、B、C 和 D 為 4 座城市,為了方便生產(chǎn)生活,要為這 4 座城市建立通信。

對(duì)于 4 個(gè)城市來講,本著節(jié)約經(jīng)費(fèi)的原則,只需要建立 3 個(gè)通信線路即可,就如圖 1(b)中的任意一種方式。

在具體選擇采用(b)中哪一種方式時(shí),需要綜合考慮城市之間間隔的距離,建設(shè)通信線路的難度等各種因素,將這些因素綜合起來用一個(gè)數(shù)值表示,當(dāng)作這條線路的權(quán)值。

假設(shè)通過綜合分析,城市之間的權(quán)值如圖 2(a)所示,對(duì)于(b)的方案中,選擇權(quán)值總和為 7 的兩種方案最節(jié)約經(jīng)費(fèi)。

這就是要討論的最小生成樹的問題,簡單得理解就是給定一個(gè)帶有權(quán)值的連通圖(連通網(wǎng)),如何從眾多的生成樹中篩選出權(quán)值總和最小的生成樹,即為該圖的最小生成樹。

  • 普里姆算法
  • 給定一個(gè)連通網(wǎng),求最小生成樹的方法有:普里姆(Prim)算法和克魯斯卡爾(Kruskal)算法。
  • 普里姆算法在找最小生成樹時(shí),將頂點(diǎn)分為兩類,一類是在查找的過程中已經(jīng)包含在樹中的(假設(shè)為 A 類),剩下的是另一類(假設(shè)為 B 類)。
  • 對(duì)于給定的連通網(wǎng),起始狀態(tài)全部頂點(diǎn)都?xì)w為 B 類。
  • 在找最小生成樹時(shí),選定任意一個(gè)頂點(diǎn)作為起始點(diǎn),并將之從 B 類移至 A 類;
  • 然后找出 B 類中到 A 類中的頂點(diǎn)之間權(quán)值最小的頂點(diǎn),將之從 B 類移至 A 類
  • 如此重復(fù),直到 B 類中沒有頂點(diǎn)為止。所走過的頂點(diǎn)和邊就是該連通圖的最小生成樹。
  • 例如,通過普里姆算法查找圖 2(a)的最小生成樹的步驟為:
  • 假如從頂點(diǎn)A出發(fā),頂點(diǎn) B、C、D 到頂點(diǎn) A 的權(quán)值分別為 2、4、2,所以,對(duì)于頂點(diǎn) A 來說,頂點(diǎn) B 和頂點(diǎn) D 到 A 的權(quán)值最小,假設(shè)先找到的頂點(diǎn) B:

  • 繼續(xù)分析頂點(diǎn) C 和 D,頂點(diǎn) C 到 B 的權(quán)值為 3,到 A 的權(quán)值為 4;
  • 頂點(diǎn) D 到 A 的權(quán)值為 2,到 B 的權(quán)值為無窮大(如果之間沒有直接通路,設(shè)定權(quán)值為無窮大)。
  • 所以頂點(diǎn) D 到 A 的權(quán)值最小:

  • 最后,只剩下頂點(diǎn) C,到 A 的權(quán)值為 4,到 B 的權(quán)值和到 D 的權(quán)值一樣大,為 3。所以該連通圖有兩個(gè)最小生成樹:

#include <stdio.h> #include <stdlib.h> #define VertexType int #define VRType int #define MAX_VERtEX_NUM 20 #define InfoType char #define INFINITY 65535typedef struct {VRType adj; //對(duì)于無權(quán)圖,用 1 或 0 表示是否相鄰;對(duì)于帶權(quán)圖,直接為權(quán)值。InfoType * info; //弧額外含有的信息指針 }ArcCell,AdjMatrix[MAX_VERtEX_NUM][MAX_VERtEX_NUM];typedef struct {VertexType vexs[MAX_VERtEX_NUM]; //存儲(chǔ)圖中頂點(diǎn)數(shù)據(jù)AdjMatrix arcs; //二維數(shù)組,記錄頂點(diǎn)之間的關(guān)系int vexnum,arcnum; //記錄圖的頂點(diǎn)數(shù)和弧(邊)數(shù) }MGraph;//根據(jù)頂點(diǎn)本身數(shù)據(jù),判斷出頂點(diǎn)在二維數(shù)組中的位置 int LocateVex(MGraph G,VertexType v){int i=0;//遍歷一維數(shù)組,找到變量vfor (; i<G.vexnum; i++) {if (G.vexs[i]==v) {return i;}}return -1; }//構(gòu)造無向網(wǎng) void CreateUDN(MGraph* G){scanf("%d,%d",&(G->vexnum),&(G->arcnum));for (int i=0; i<G->vexnum; i++) {scanf("%d",&(G->vexs[i]));}for (int i=0; i<G->vexnum; i++) {for (int j=0; j<G->vexnum; j++) {G->arcs[i][j].adj=INFINITY;G->arcs[i][j].info=NULL;}}for (int i=0; i<G->arcnum; i++) {int v1,v2,w;scanf("%d,%d,%d",&v1,&v2,&w);int m=LocateVex(*G, v1);int n=LocateVex(*G, v2);if (m==-1 ||n==-1) {printf("no this vertex\n");return;}G->arcs[n][m].adj=w;G->arcs[m][n].adj=w;} }//輔助數(shù)組,用于每次篩選出權(quán)值最小的邊的鄰接點(diǎn) typedef struct {VertexType adjvex;//記錄權(quán)值最小的邊的起始點(diǎn)VRType lowcost;//記錄該邊的權(quán)值 }closedge[MAX_VERtEX_NUM]; closedge theclose;//創(chuàng)建一個(gè)全局?jǐn)?shù)組,因?yàn)槊總€(gè)函數(shù)中都會(huì)使用到//在輔助數(shù)組中找出權(quán)值最小的邊的數(shù)組下標(biāo),就可以間接找到此邊的終點(diǎn)頂點(diǎn)。 int minimun(MGraph G,closedge close){int min=INFINITY;int min_i=-1;for (int i=0; i<G.vexnum; i++) {//權(quán)值為0,說明頂點(diǎn)已經(jīng)歸入最小生成樹中;然后每次和min變量進(jìn)行比較,最后找出最小的。if (close[i].lowcost>0 && close[i].lowcost < min) {min=close[i].lowcost;min_i=i;}}//返回最小權(quán)值所在的數(shù)組下標(biāo)return min_i; }//普里姆算法函數(shù),G為無向網(wǎng),u為在網(wǎng)中選擇的任意頂點(diǎn)作為起始點(diǎn) void miniSpanTreePrim(MGraph G,VertexType u){//找到該起始點(diǎn)在頂點(diǎn)數(shù)組中的位置下標(biāo)int k=LocateVex(G, u);//首先將與該起始點(diǎn)相關(guān)的所有邊的信息:邊的起始點(diǎn)和權(quán)值,存入輔助數(shù)組中相應(yīng)的位置,例如(1,2)邊,adjvex為0,lowcost為6,存入theclose[1]中,輔助數(shù)組的下標(biāo)表示該邊的頂點(diǎn)2for (int i=0; i<G.vexnum; i++) {if (i !=k) {theclose[i].adjvex=k;theclose[i].lowcost=G.arcs[k][i].adj;}}//由于起始點(diǎn)已經(jīng)歸為最小生成樹,所以輔助數(shù)組對(duì)應(yīng)位置的權(quán)值為0,這樣,遍歷時(shí)就不會(huì)被選中theclose[k].lowcost=0;//選擇下一個(gè)點(diǎn),并更新輔助數(shù)組中的信息for (int i=1; i<G.vexnum; i++) {//找出權(quán)值最小的邊所在數(shù)組下標(biāo)k=minimun(G, theclose);//輸出選擇的路徑printf("v%d v%d\n",G.vexs[theclose[k].adjvex],G.vexs[k]);//歸入最小生成樹的頂點(diǎn)的輔助數(shù)組中的權(quán)值設(shè)為0theclose[k].lowcost=0;//信息輔助數(shù)組中存儲(chǔ)的信息,由于此時(shí)樹中新加入了一個(gè)頂點(diǎn),需要判斷,由此頂點(diǎn)出發(fā),到達(dá)其它各頂點(diǎn)的權(quán)值是否比之前記錄的權(quán)值還要小,如果還小,則更新for (int j=0; j<G.vexnum; j++) {if (G.arcs[k][j].adj<theclose[j].lowcost) {theclose[j].adjvex=k;theclose[j].lowcost=G.arcs[k][j].adj;}}}printf("\n"); }int main(){MGraph G;CreateUDN(&G);miniSpanTreePrim(G, 1); }

2.克魯斯卡爾算法(Kruskal算法)求最小生成樹

3.拓?fù)渑判蛩惴?/h3>

4.迪杰斯特拉(Dijkstra算法)算法

5.弗洛伊德算法

2,3,4,5算法詳解請(qǐng)點(diǎn)擊:https://blog.csdn.net/wolfGuiDao/article/details/107593373

總結(jié)

以上是生活随笔為你收集整理的数据结构--图(Graph)详解(三)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。