圖的定義與術(shù)語

1、圖按照有無方向分為無向圖和有向圖。無向圖由頂點和邊構(gòu)成,有向圖由頂點和弧構(gòu)成。弧有弧尾和弧頭之分。

2、如果任意兩個頂點之間都存在邊叫完全圖,有向的叫有向完全圖。若無重復(fù)的邊或頂點到自身的邊則叫簡單圖。

3、圖中頂點之間有鄰接點、依附的概念。無向圖頂點的邊數(shù)叫做度,有向圖頂點分為入度和出度。

4、圖上的邊或弧上帶權(quán)則稱為網(wǎng)。

5、圖中頂點間存在路徑,兩頂點存在路徑則說明是連通的,如果路徑最終回到起始點則稱為環(huán),當(dāng)中不重復(fù)叫簡單路徑。若任意兩頂點都是連通的,則圖就是連通圖,有向則稱為強(qiáng)連通圖。

6、無向圖中連通且n個頂點n-1條邊叫生成樹。有向圖中一頂點入度為0其余頂點入度為1的叫有向樹。

圖的存儲結(jié)構(gòu)

鄰接矩陣

圖的鄰接矩陣存儲方式是用兩個數(shù)組來表示圖。一個一維數(shù)組存儲圖中頂點信息,一個二維數(shù)組存儲圖中的邊或弧的信息。

鄰接矩陣存儲的結(jié)構(gòu)代碼如下:

typedef? char VertexType;/*頂點類型應(yīng)由用戶定義*/

typedef int? EdgeType;/*邊上的權(quán)值類型應(yīng)由用戶定義*/

#define MAXVEX? 100//最大頂點數(shù),由用戶定義

#define INFINITY? 65535//用65535來代表無限

typedef struct {

???? VertexType vexs[MAXVEX];//頂點表

???? EdgeType arc[MAXVEX][MAXVEX];//鄰接矩陣,可看作邊表

???? int? numVertexes, numEdges;//圖中當(dāng)前的頂點數(shù)和邊數(shù)

}MGraph;

/*建立無向網(wǎng)圖的鄰接矩陣表示*/

void CreateMGraph(MGraph *G) {

??? int i,j,k,w;

??? printf("輸入頂點數(shù)和邊數(shù):\n");

??? scanf("%d,%d",&G->numVertexes,&G->numEdges);/*輸入頂點數(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];/*因為是無向圖,矩陣對稱*/

?????? }

}

鄰接表

鄰接表存儲方法:

1、圖中頂點用一維數(shù)組存儲,每個數(shù)據(jù)元素存儲指向第一個鄰接點的指針,以便于查找該頂點的邊信息。

2、圖中每個頂點vi的所有鄰接點構(gòu)成一個線性表,由于鄰接點的個數(shù)不定,所以用單鏈表存儲,無向圖稱為頂點vi的邊表,有向圖則稱為頂點vi作為弧尾的出邊表。

結(jié)點定義代碼:

typedef char? VertexType;/*頂點類型應(yīng)由用戶定義*/

typedef? int EdgeType;/*邊上的權(quán)值類型應(yīng)由用戶定義*/

typedef? struct? EdgeNode/*邊表結(jié)點*/

{
??? int adjvex;???????????????????????? /*鄰接點域,存儲該頂點對應(yīng)下標(biāo)*/

??? EdgeType? weight;?????????? /*用于存儲權(quán)值,對于非網(wǎng)圖可以不需要*/

??? struct? EdgeNode *next; /*鏈域,指向下一個鄰接點*/

}EdgeNode;

typedef struct VertexNode/*頂點表結(jié)點*/

{
???? VertexType data;?????????? /*頂點域,存儲頂點信息*/

???? EdgeNode? *firstedge;/*邊表頭指針*/

}VertexNode,AdjList[MAXVEX];

typedef? struct{

???? AdjList adjList;

???? int? numVertexes,numEdges;??? /*圖中當(dāng)前頂點數(shù)和邊數(shù)*/

}GraphAdjList;

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

/*建立圖的鄰接表結(jié)構(gòu)*/

void? CreateALGraph(GraphAdjList *G) {

???? int i,j,k;

???? EdgeNode? *e;

???? printf("輸入頂點數(shù)和邊數(shù):\n");

????? scanf("%d,%d",&G->numVertexes,&G->numEdges);/*輸入頂點數(shù)和邊數(shù)*/

????? for(i = 0; i < G->numVertexes;i++)/*讀入頂點信息,建立頂點表*/

?????? {

????????????????? scanf(&G->adjList[i].data);/*輸入頂點信息*/

????????????????? G->adjList[i].firstedge=NULL;/*將邊表置空*/

???????? }

??????? for(k = 0; k < G->numEdges;k++) {/*建立邊表*/

??????????????? printf("輸入邊(vi,vj)上的頂點序號:\n");

???????????????? scanf("%d,%d",&i, &j);/*輸入邊(vi,vj)上的頂點序號*/

???????????????? e=(EdgeNode*)malloc(sizeof(EdgeNode));/*向內(nèi)存申請空間,生成邊表結(jié)點*/

???????????????? e->adjvex=j;/*鄰接序號為j*/

???????????????? e->next=G->adjList[i].firstedge;/*將e指針指向當(dāng)前頂點指向的結(jié)點*/

???????????????? G->adjList[i].firstedge=e;/*將當(dāng)前頂點的指針指向e*/

???????????????? e=(EdgeNode*)malloc(sizeof(EdgeNode));/*向內(nèi)存申請空間,生成邊表結(jié)點*/

????????????????? e->adjvex=i;

???????????????? e->next=G->adjList[j].firstedge;/*將e指針指向當(dāng)前頂點指向的結(jié)點*/

???????????????? G->adjList[j].firstedge=e;/*將當(dāng)前頂點的指針指向e*/

?????????? }

}

剩余的圖的存儲結(jié)構(gòu)還有,十字鏈表,鄰接多重表,邊集數(shù)組。

圖的遍歷

深度優(yōu)先遍歷

//鄰接矩陣的深度優(yōu)先遍歷

typedef int Boolean;? /*Boolean是布爾類型,其值是TRUE或FALSE*/

Boolean visited[MAX];/*訪問標(biāo)志的數(shù)組*/

/*鄰接矩陣的深度優(yōu)先遞歸算法*/

void DFS(MGraph G, int i) {

? ? int j;

? ? visited[i] = TRUE;

? ? printf("%c", G.vexs[i]);/*打印頂點,也可以其他操作*/

? ? ?for(j = 0; j < G.numVertexes; j++)

? ? ? ? ? ? ? ?if(G.arc[i][j] == 1 && !visited[j])

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?DFS(G, j);/*對為訪問的鄰接頂點遞歸調(diào)用*/

}

/*鄰接矩陣的深度遍歷操作*/

void DFSTraverse(MGraph G) {

? ? int i;

? ? for(i = 0; i < G.numVertexes; i++)

? ? ? ? ? ? ? ? ? visited[i] = FALSE;/*初始所有頂點狀態(tài)都是未訪問狀態(tài)*/

? ? ? for(i = 0; i < G.numVertexes; i++)

? ? ? ? ? ? ? ? ? if(!visited[i])/*對未訪問過的頂點調(diào)用DFS,若是連通圖,只會執(zhí)行一次*/

? ? ? ? ? ? ? ? ? ? ? ? ? ? ?DFS(G, i);

}

/*鄰接表的深度優(yōu)先遞歸算法*/

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);/*對為訪問的鄰接頂點遞歸調(diào)用*/

? ? ? ? ?p = p ->next;

? ? ? ? }

}

/*鄰接表的深度遍歷操作*/

void DFSTraverse(GraphAdjList GL) {

? ? ? int i;

? ? ? ? for(i = 0; i < GL->numVertexes; i++)

? ? ? ? ? ? ? ? ? ?visited[i] = FALSE;/*初始所有頂點狀態(tài)都是未訪問過狀態(tài)*/

? ? ? ? ?for(i = 0; i < GL->numVertexes; i++)

? ? ? ? ? ? ? ? ? ?if(!visited[i])/*對未訪問過的頂點調(diào)用DFS,若是連通圖,只會執(zhí)行一次*/

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?DFS(GL, i);

}

廣度優(yōu)先遍歷

/*鄰接矩陣的廣度優(yōu)先遍歷*/

void BFSTraverse(MGraph G) {

? ? ? ?int i, j;

? ? ? ?Queue Q;

? ? ? ? for(i =0; i < G.numVertexes; i++)

? ? ? ? ? ? ? ? ?visited[i] = FALSE;

? ? ? ? ? InitQueue(&Q);/*初始化一輔助隊列*/

? ? ? ? ? for(i = 0; i < G.numVertexes; i++)/*對每一個頂點做循環(huán)*/

? ? ? ? ? ?{

? ? ? ? ? ? ? ? ? ? ? ? ? if(!visited[i]){/*若是未訪問過就處理*/

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? visited[i] = TRUE;/設(shè)置當(dāng)前頂點訪問過*/

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?printf("%c", G.vexs[i]);/*打印頂點,也可以其他操作*/

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?EnQueue(&Q,i);/*將此頂點入隊列*/

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? while(!QueueEmpty(Q)){ /*若當(dāng)前隊列不為空*/?

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? DeQueue(&Q, &i);/*將隊中元素出隊列,賦值給i*/

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?for(j = 0; j< G.numVertexes; j++) {

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? /*判斷其他頂點若與當(dāng)前頂點存在邊且未訪問過*/

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?if(G.arc[i][j] == 1 && !visited[j]) {

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?visited[j]=TRUE;/*找到的此頂點標(biāo)記已訪問*/

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?printf("%c",G.vexs[j]);/*打印頂點*/

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? EnQueue(&Q, j);/*將找到的此頂點入隊列*/

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?}

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?}

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?}

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?}

? ? ? ? ? ? ? ? ? ? }

}

/*鄰接表的廣度優(yōu)先遍歷算法*/

void BFSTraverse(GraphAdjList GL) {

? ? ? ? int i;

? ? ? ? ?EdgeNode *po;

? ? ? ? ?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)前頂點邊表鏈表頭指針*/

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? while(p) {

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?if(!visitied[p->adjvex]) {

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?visited[p->adjvex] = TRUE;

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?printf("%c", GL->adjList[p->adjvex].data);

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?EnQueue(&Q, p ->adjvex);/*將此頂點入隊列*/

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?}

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?p=p->next;

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? }

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?}

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?}

? ? ? ? ? ? ? }

}

最小生成樹

/*prim算法生成最小生成樹*/

void MiniSpanTree_Prim(MGraph G) {

? ? ? ? ? ? int min, i , j, k;

? ? ? ? ? ? int? adjvex[MAXVEX];/*保存相關(guān)頂點下標(biāo)*/

? ? ? ? ? ? int lowcost[MAXVEX];/*保存相關(guān)頂點間邊的權(quán)值*/

? ? ? ? ? ? lowcost[0] = 0;/*初始化第一個權(quán)值為0,即V0加入生成樹*/

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?/*lowcost的值為0,在這里就是此下標(biāo)的頂點已經(jīng)加入生成樹*/

? ? ? ? ? ? adjvex[0] = 0;/*初始化第一個頂點下標(biāo)為0*/

? ? ? ? ? ? for(i = 1; i < G.numVertexes; i ++)/*循環(huán)除小標(biāo)為0外的全部頂點*/

? ? ? ? ? ? {

? ? ? ? ? ? ? ? ? ? ? ? ? ? ?lowcost[i] = G.arc[0][i];/*將V0頂點與之有邊的權(quán)值存入數(shù)組*/

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? adjvex[i] = 0;/*初始化都為V0的下標(biāo)*/

? ? ? ? ? ? ?}

? ? ? ? ? ? for(i = 0; i < G.numVertexes; i++) {

? ? ? ? ? ? ? ? ? ? ? ?min = INFINITY;/*初始化最小權(quán)值*/

? ? ? ? ? ? ? ? ? ? ? j = 1; k = 0;

? ? ? ? ? ? ? ? ? ? ? while(j < G.numVertexes) { /*循環(huán)全部頂點*/

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? if(lowcost[j] != 0 && lowcost[j] < min) {/*如果權(quán)值不為0且權(quán)值小于min*/

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? min = lowcost[j];? ? ? ? ? ? ? ? ? ? ? /*則讓當(dāng)前權(quán)值成為最小值*/

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?k = j;

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? }

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?j++;

? ? ? ? ? ? ? ? ? ? ? ? ?}

? ? ? ? ? ? ? ? ? ? ? ? printf("(%d,%d)",adjvex[k], k);/*打印當(dāng)前頂點邊中權(quán)值最小邊*/

? ? ? ? ? ? ? ? ? ? ? ? ?lowcost[k] = 0;/*將當(dāng)前頂點的權(quán)值設(shè)置為0,表示此頂點已經(jīng)完成任務(wù)*/

? ? ? ? ? ? ? ? ? ? ? ? for(j = 1; j < G.numVertexes; j ++)/*循環(huán)所有頂點*/

? ? ? ? ? ? ? ? ? ? ? ? ? {

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?if(lowcost[j] != && G.arc[k][j] <lowcost[j]) {

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?/*若小標(biāo)為k頂點各邊權(quán)值小于此前這些頂點未被加入生成樹權(quán)值*/

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? lowcost[j] = G.arc[i][j];/*將較小權(quán)值存入lowcost*/

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?adjvex[j] = k;/*將下標(biāo)為k的頂點存入adjvex*/

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?}

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?}

? ? ? ? ? ? ? ? ? ? }

}

/*Kruskal算法生成最小生成樹*/

void MiniSpanTree_Kruskal(MGraph G) /*生成最小生成樹*/

{

? ? ? ? ? int i, n , m;

? ? ? ? ? ?Edge edges[MAXEDGE];/*定義邊集數(shù)組*/

? ? ? ? ? int parent[MAXVEX];/*定義一數(shù)組用來判斷邊與邊是否形成回路*/

? ? ? ? ? ?/*此處省略將鄰接矩陣G轉(zhuǎn)化為邊集數(shù)組edges并按權(quán)有小到大排序的代碼*/

? ? ? ? ?for(i = 0; i < G.numVertexes; i++)

? ? ? ? ? ? ? ? ? ? ?parent[i] = 0;/*初始化數(shù)組值為0*/

? ? ? ? for(i = 0; i <G.numEdges; i++) { /*循環(huán)每一條邊*/

? ? ? ? ? ? ? ? ? ? n = Find(parent, edges[i].begin);

? ? ? ? ? ? ? ? ? ? ?m = Find(parent, edges[i].end);

? ? ? ? ? ? ? ? ? ? if(n != m)/*假如n與m不等,說明此邊沒有與現(xiàn)有生成樹形成環(huán)路*/

? ? ? ? ? ? ? ? ? ? ? {

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?parent[n] = m;/*將此邊的結(jié)尾頂點放入下標(biāo)為起點的parent中,表示此頂點已經(jīng)在生成樹集合中*/

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? printf("(%d, %d) %d", edges[i].begin, edges[i].end, edges[i].weight);

? ? ? ? ? ? ? ? ? ? ? ? ?}

? ? ? ? ? ? ? ?}

}

int Find(int *parent, int f) /*查找連線頂點的尾部下標(biāo)*/

{

? ? ?while(parent[f]>0)

? ? ? ? ? ? ? f = parent[f];

? ? ?return f;

}

最短路徑

對于網(wǎng)圖來說,最短路徑,是指兩頂點之間經(jīng)過的邊上權(quán)值之和最少的路徑,并且我們稱路徑上的第一個頂點是源點,最后一個頂點是終點。

Dijkstra算法

#define? MAXVEX? 9

#define INFINITY 65535

typedef? int? Patharc[MAXVEX];/*用于存儲最短路徑下標(biāo)的數(shù)組*/

typdef? int ShortPathTable[MAXVEX];/*用于存儲到各點最短路徑的權(quán)值和*/

/*Dijkstra算法,求有向網(wǎng)G的V0頂點到其余頂點V最短路徑P[v]及帶權(quán)長度D[v]*/

/* P[v]的值為前驅(qū)頂點下標(biāo),D[v]表示V0到V的最短路徑長度和。*/

void? ShortestPath_Dijkstra (MGraph G,int v0, Patharc *p, ShortPathTable *D) {

??? int v, w, k ,min;

???? int? final[MAXVEX];/*final[w]=1表示求得頂點V0至Vw的最短路徑*/

???? for(v=0; v< G.numberVertexes; v++)/*初始化數(shù)據(jù)*/

???? {

?????????????? final[v]= 0;/*全部頂點初始化為未知最短路徑狀態(tài)*/

??????????????? (*D)[v]= G.arc[v0][v];/*將與V0點有連線的頂點加上權(quán)值*/

???????????????? (*P)[v]=0;/*初始化路徑數(shù)組P為0*/

????????? }

?????? (*D)[v0] = 0;/*V0至V0路徑為0*/

??????? final[v0] = 1;/*V0至V0不需要路徑*/

??????? /*開始主循環(huán),每次求得V0到某個V頂點的最短路徑*/

?????? for(v=1; v< G.numVertexes; v++) {

?????????????????? min = INFINITY;/*當(dāng)前所知離V0頂點的最近距離*/

??????????????????? for(w=0; w<G.numVertexes; w++)/*尋找離V0最近的頂點*/

?????????????????? {

??????????????????????????????? if(!final[w] && (*D)[w]<min){

????????????????????????????????????????????? k = w;

?????????????????????????????????????????????? min=(*D)[w];/*w頂點離V0頂點更近*/

???????????????????????????????????? }

????????????????????????? }

???????????????????????? final[k] = 1;/*將目前找到的最近的頂點置為1*/

??????????????????????? for(w=0; w < G.numVertexes; w++) /*修正當(dāng)前最短路徑及距離*/

??????????????????????? {

???????????????????????????????????????? /*如果經(jīng)過V頂點的路徑比現(xiàn)在這條路徑的長度短的話*/

???????????????????????????????????????? if(!final[w]&& (min + G.arc[k][w] < (*D)[w]))

???????????????????????????????????????? {/*說明找到了更短的路徑,修改D[w]和P[w]*/

??????????????????????????????????????????????????????? (*D)[w] = min+G.arc[k][w];/*修改當(dāng)前路徑長度*/

????????????????????????????????????????????????????????? (*P)[w]= k;

???????????????????????????????????????????? }

??????????????????????????????? }

?????????????? }

}

Floyd算法

typedef int Pathmatirx[MAXVEX][MAXVEX];

typedef int ShortPathTable[MAXVEX][MAXVEX];

/*Floyd算法,求網(wǎng)圖G中各頂點v到其余頂點w最短路徑P[v][w]及帶權(quán)長度D[v][w]*/

void ShortestPath_Floyd(MGraph G, Pathmatirx *P, ShortPathTable *D) {

???? int? v, w, k;

???? for(v = 0; v < G.numVertexes; ++v)/*初始化D與P*/

????? {

????????????????? for(w = 0; w < G.numVertexes; ++w)

??????????????? {

??????????????????????????? (*D)[v][w] = G.matirx[v][w];/*D[v][w]值即為對應(yīng)點間的權(quán)值*/

????????????????????????????? (*P)[v][w] = w;/*初始化P*/

????????????????? }

??????????? }

??????????? for(k = 0; k < G.numVertexes; ++k)

???????????? {

?????????????????????? for(v = 0; v < G.numVertexes; ++v)

?????????????????????? {

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?? for(w=0; w < G.numVertexes; ++w)

???????????????????????????????????? {

????????????????????????????????????????????????? if((*D)[v][w]>(*D)[v][k]+(*D)[k][w])

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?? {/*如果經(jīng)過下標(biāo)為k頂點路徑比原兩點間路徑更短*/

???????????????????????????????????????????????????? /*將當(dāng)前兩點間權(quán)值設(shè)為更小的一個*/

???????????????????????????????????????????????????????????????? (*D)[v][w] = (*D)[v][k] + (*D)[k][w];

????????????????????????????????????????????????????????????????? (*P)[v][w]= (*P)[v][k];/*路徑設(shè)置經(jīng)過下標(biāo)為k的頂點*/????????

????????????????????????????????????????? }

???????????????????????????? }

?????????????? }

???? }

}

求最短路徑代碼

for(v=0; v< G.numVertexes; v++)

{

????????? for(w = v+ 1; w < G.numVertexes; w++)

????????? {

????????????????????? printf("v%d-v%d weight:%d",v, w, D[v][w]);

???????????????????? k =P[v][w];/*獲得第一個路徑頂點下標(biāo)*/

????????????????????? printf("path: %d",v);/*打印源點*/

?????????????????????? while(k!=w)/*如果路徑頂點下標(biāo)不是終點*/

?????????????????????? {

????????????????????????????????? printf("-> %d", k );/*打印路徑頂點*/

??????????????????????????????????? k=P[k][w];/*獲得下一個路徑頂點下標(biāo)*/

???????????????????????? }

??????????????????????? printf("-> %d\n",w);/*打印終點*/

??????????????? }

???????????????? printf("\n");

}

拓?fù)渑判?/h2>

設(shè)G=(V,E)是一個具有n個頂點的有向圖,V中的頂點序列v1,v2,·····,vn,滿足若從頂點vi到vj有一條路徑,則在頂點序列中頂點vi必在頂點vj之前。則我們稱這樣的頂點序列為一個拓?fù)湫蛄小?/p>

所謂拓?fù)渑判颍鋵嵕褪菍σ粋€有向圖構(gòu)造拓?fù)湫蛄械倪^程。

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

結(jié)構(gòu)代碼:

typedef struct EdgeNode/*邊表結(jié)點*/

{
??????? int adjvex;/*鄰接點域,存儲該頂點對應(yīng)的下標(biāo)*/

??????? int weight;/*用于存儲權(quán)值,對于非網(wǎng)圖可以不需要*/

??????? struct EdgeNode *next;/*鏈域,指向下一個鄰接點*/

}EdgeNode;


typedef struct VertexNode/*頂點表結(jié)點*/

{
??????? int in;/*頂點入度*/

???????? int? data;/*頂點域,存儲頂點信息*/

??????? EdgeNode *firstedge;/*邊表頭指針*/

}VertexNode,AdjList[MAXVEX];


typedef struct

{

????? AdjList adjList;

?????? int numVertexes, numEdges;/*圖中當(dāng)前頂點數(shù)和邊數(shù)*/

}graphAdjList, *GraphAdjList;

/*拓?fù)渑判?,若GL無回路,則輸出拓?fù)渑判蛐蛄胁⒎祷豋K,若有回路返回ERROR*/

Status TopologicalSort(GraphAdjList GL)

{

??????? EdgeNode *e;

???????? int i, k, gettop;

????????? int top= 0;/*用于棧指針下標(biāo)*/

??????? int count = 0;/*用于統(tǒng)計輸出頂點的個數(shù)*/

???????? int *stack;/*建棧存儲入度為0的頂點*/

??????? stack = (int *)malloc(GL->numVertexes * sizeof(int));

??????? for(i = 0; i < GL->numVertexes; i++)

?????????????? if(GL->adjList[i].in == 0)

?????????????????????? stack[++top] = i;/*將入度為0的頂點入棧*/

?????? while(top != 0)

?????? {

?????????????? gettop=stack[top--];/*出棧*/

??????????????? printf("%d -> ",GL->adjList[gettop].data);/*打印此頂點*/

?????????????? count++;/*統(tǒng)計輸出頂點數(shù)*/

????????????? for(e=GL->adjList[gettop].firstedge; e; e= e->next)

????????????? {/*對此頂點弧表遍歷*/

???????????????????????? k=e->adjvex;

??????????????????????? if(!(--GL->adjList[k].in))/*將k號頂點鄰接點的入度減1*/

???????????????????????????????????? stack[++top]=k;/*若為0則入棧,以便于下一次循環(huán)輸出*/

???????????????? }

?????? }

????? if(count<GL->numVertexes)/*如果count小于頂點數(shù),說明存在環(huán)*/

??????????????? return? ERROR;

??????? else

??????????????? return OK;

}

關(guān)鍵路徑

路徑上各個活動所持續(xù)的時間之和稱為路徑長度,從源點到匯點具有最大長度的路徑叫關(guān)鍵路徑,在關(guān)鍵路徑上的活動叫關(guān)鍵活動。

關(guān)鍵路徑算法

全局變量:

int *etv,*ltv;/*事件最早發(fā)生時間和最遲發(fā)生時間數(shù)組*/

int *stack2;/*用于存儲拓?fù)湫蛄械臈?/

int top2;/*用于stack2的指針*/

/*拓?fù)渑判?,用于關(guān)鍵路徑計算*/

Status TopologicalSort(GraphAdjList GL) {

????? EdgeNode *e;

?????? int i, k, gettop;

?????? int top = 0;/*用于棧指針下標(biāo)*/

?????? int count = 0;/*用于統(tǒng)計輸出頂點的個數(shù)*/

?????? int *stack;/*建棧將入度為0的頂點入棧*/

??????? stack = (int *)malloc(GL->numVertexes * sizeof(int));

?????? for(i = 0; i < GL.numVertexes; i++)

??????????????? if(0 == GL->adjList[i].in)

?????????????????????? stack[++top] = i;

?????? top2= 0;/*初始化為0*/

??????? etv=(int *)malloc(GL->numVertexes * sizeof(int));/*事件最早發(fā)生時間*/

??????? for(i = 0; i < GL->numVertexes; i++)

???????????????? etv[i]=0;/*初始化為0*/

????????? stack2=(int *)malloc(GL->numVertexes * sizeof(int));/*初始化*/

????????? while(top != 0) {

????????????????? gettop=stack[top--];

????????????????? count++;

????????????????? stack2[++top2] =gettop;/*將彈出的頂點序號壓入拓?fù)湫蛄械臈?/

?????????????????? for(e = GL->adjList[gettop].firstedge; e; e= e->next) {

????????????????????????????? k = e->adjvex;

????????????????????????????? if(!(--GL->adjList[k].in))

?????????????????????????????????????? stack[++top]=k;

??????????????????????????????? if((etv[gettop] + e->weight)>etv[k])/*求各頂點事件最早發(fā)生時間值*/

?????????????????????????????????????????? etv[k] = etv[gettop] + e->weight;

???????????????????????? }

???????????? }

????????????? if(count < GL->numVertexes)

?????????????????????? return ERROR;

?????????????? else

??????????????????????? return OK;

}

/*求關(guān)鍵路徑,GL為有向網(wǎng),輸出GL的各項關(guān)鍵活動*/

void CriticalPath(GraphAdjList GL) {

???????? EdgeNode *e;

???????? int? i, gettop, k ,j;

????????? int ete, lte;/*聲明活動最早發(fā)生時間和最遲發(fā)生時間變量*/

? ? ? ? ? TopologicalSort(GL);/*求拓?fù)湫蛄校嬎銛?shù)組etv和stack2的值*/

? ? ? ? ? ? ltv = (int *)malloc(GL->numVertexes * sizeof(int));/*事件最晚發(fā)生時間*/

? ? ? ? ? for(i = 0; i < GL->numVertexes; i++)

?????????????????? ltv[i] = etv[GL->numVertexes - 1];/*初始化ltv*/

?????????? while(top2 ! = 0)/*計算ltv*/

? ? ? ? ? {

???????????????????? gettop=stack2[top2--];/*將拓?fù)湫蛄谐鰲?,后進(jìn)先出*/

? ? ? ? ? ? ? ? ??? for(e = GL->adjList[gettop].firstedge; e; e = e->next) {

? ? ? ? ? ? ? ? ? ?? /*求各頂點事件的最遲發(fā)生時間ltv值*/

??????????????????????????????? k = e->adjvex;

??????????????????????????????? if(ltv[k]- e->weight < ltv[gettop])/*求各頂點事件最晚發(fā)生時間ltv*/

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ltv[gettop] = ltv[k] - e->weight;

???????????????????????? }

???????????? }

???????????? for(j=0; j < GL->numVertexes; j++)/*求ete,lte和關(guān)鍵活動*/

???????????? {

??????????????????????? for(e->GL->adjList[j].firstedge; e; e= e->next) {

???????????????????????? {

?????????????????????????????????????? k= e->adjvex;

??????????????????????????????????????? ete =etv[j];/*活動最早發(fā)生時間*/

??????????????????????????????????????? lte=ltv[k] -e->weight;/*活動最遲發(fā)生時間*/

??????????????????????????????????????? if(ete == lte)/*兩者相等即在關(guān)鍵路徑上*/

????????????????????????????????????????????????? printf("<v%d,v%d> length: %d,",GL->adjList[j].data, GL->adjList[k].data,e->weight);

???????????????????????????????? }

????????????????? }

}

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,825評論 6 546
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 99,814評論 3 429
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,980評論 0 384
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 64,064評論 1 319
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 72,779評論 6 414
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 56,109評論 1 330
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 44,099評論 3 450
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 43,287評論 0 291
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 49,799評論 1 338
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 41,515評論 3 361
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,750評論 1 375
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,221評論 5 365
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 44,933評論 3 351
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,327評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,667評論 1 296
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,492評論 3 400
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 48,703評論 2 380

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