14、最小生成樹問題(**)
【問題描述】
若要在n
個城市之間建設通訊網路,只需要假設
n-1條線路即可。如何以最低的經濟代價建設這個通訊網,是乙個網的最小生成樹問題。
【系統要求】
1.利用克魯斯卡爾演算法求網的最小生成樹。
2.利用普里姆演算法求網的最小生成樹。
3.要求輸出各條邊及它們的權值。
【測試資料】
由學生任意指定,但報告上要求寫出多批資料測試結果。
【實現提示】
通訊線路一旦建成,必然是雙向的。因此,構造最小生成樹的網一定是無向網。設圖的頂點數不超過
30個,並為簡單起見,網中邊的權值設成小於
100的整數,可利用
c語言提供的隨機函式產生。
圖的儲存結構的選取應和所作操作相適應。為了便於選擇權值最小的邊,此題的儲存結構既不選用鄰接矩陣的陣列表示法,也不選用鄰接表,而是以儲存邊(帶權)的陣列表示圖。
【選作內容】
利用堆排序實現選擇權值最小的邊。
一、演算法設計
1.隨機生成圖我利用的是c語言中的random()和rang()函式,採取系統時間為隨機種子,再生成隨機數,保證每次生成的圖不相同。因為我所構造的圖的儲存是30*30的鄰接矩陣,在構造圖的過程中利用隨機函式先產生1~30之間的30個隨機數。然後從第乙個數開始,判斷之後的數是否與它相同,如果不同就再利用隨機函式生成乙個1~90之間的隨機數作為邊的權值。而第乙個數作為邊的始點,第二個數作為邊的終點,儲存進鄰接矩陣。當然這不能夠保證生成的圖是聯通的。所以對鄰接矩陣進行一次遍歷。如果該行所有數全部為0,就產生乙個與此時行數不同的1~30之間的數,乙個1~90之間的數,重新進行儲存,保證生成的圖肯定是乙個連通圖。然後在進行一趟遍歷,統計總共有的邊數,同時遍歷的過程檢查是否為無向圖,如果不是,行列互換位置賦值,保證是無向圖。邊集陣列構造好之後需要按照權重大小進行排序,這裡我利用的是快速排序,與題目的中的堆排序有些出入。邊集陣列是為克魯斯卡爾演算法做準備的,每次加入一條邊檢查是否屬於構成了環,所以還需要利用乙個輔助陣列來標記,記為father陣列,類似於並查集中的思想。對於普里姆演算法,需要將原來的鄰接矩陣重新修整,所有為0的地方全部變為inf(即假定的無窮大數值)。在最後計算總花費的時候再利用原來的鄰接矩陣計算。
各個函式之間的呼叫關係如下圖所示:
main()
mainjiemian()
creatgraph()
prim()
quicksort()
kruskal()
jieshu()
partion()
find()
mainjiemian()
2.本程式中包含8個模組
(1)主函式:int main();
(2)結束函式:void jieshu();
(3)主介面函式:void mainjiemian();
(4)克魯斯卡爾演算法:void kruskal(edgetype edge[max_edge_num]);
(5)快速排序函式:
void quicksort(edgetype edge[max_edge_num],int low, int high)
int partion(edgetype edge[max_edge_num], intlow, int high)
(6)尋找根結點:int find(intfather[maxvertexnum], int v);
(7)普里姆演算法:void prim(graph*g,int w[100], int fa, int n);
(8)隨機生成圖:voidcreatgraph(graph *g);
3.元素型別、結點型別和指標型別
#define inf 65535
#define maxvertexnum 35 /*最大頂點數為30*/
#define max_edge_num 1000
typedef int vertextype; /*頂點型別設定為字元型*/
typedef int edgetype; /*邊的權值設為整型*/
typedef struct
graph; /*graph是以鄰接矩陣儲存的圖型別*/
typedef struct
edgetype;
二、實驗測試
圖的生成並不是固定的隨機方法,可以保證前後無關聯性
源**:
#include#include#include#include#include#include#include#include#include#include#includeusing namespace std;int edgenum = 0;
#define inf 65535
#define maxvertexnum 35 /*最大頂點數為30*/
#define max_edge_num 1000
typedef int vertextype; /*頂點型別設定為字元型*/
typedef int edgetype; /*邊的權值設為整型*/
typedef struct
graph; /*graph是以鄰接矩陣儲存的圖型別*/
typedef struct
edgetype;
edgetype edge[max_edge_num]; /*定義邊集陣列*/
void creatgraph(graph *g) /*建立無向圖g的鄰接矩陣儲存*/
} for (i = 0; i < 30; i++)
ans[i] = rand() % 30 + 1; /*產生隨機的城市*/
for (i = 0; i < 30; i++) /*隨機生成權值,構造鄰接矩陣*/
}} for (i = 1; i <= g->n; i++)/*完善整個圖,使之必定為連通圖*/
}if (!flag)
int v = rand() % 90 + 1;
g->edges[i][t] = v;
g->edges[t][i] = v;
} }for (i = 1; i <= 30; i++) }
i = 1;
while (i <= edgenum)
}} }
for (i = 1; i <= g->n; i++)
printf("\n"); }}
void prim(graph *g,int w[100], int fa, int n)
for (i = 2; i <= n; i++) }
printf("最小生成樹如下:\n");
int cost = 0;
for (int i = 2; i <= 30; i++) /*列印結果*/
printf("最少花費成本為:%d\n", cost);
}int find(int father[maxvertexnum], int v)/*尋找頂點v所在樹的根節點*/
return v;
}int partion(edgetype edge[max_edge_num], int low, int high)/*對邊集陣列進行排序*/
case'2':
}prim(g, w, fa, g->n);
system("pause");
system("cls");
mainjiemian();
break;
} case'3':
case'4':
default:
}} return 0;
}
資料結構 最小生成樹問題
假設n 是乙個連通網,u是頂點集v的乙個非空子集,若 u,v 是一條具有最小權值的邊,其中u u,v v u,則比存在一棵包含邊 u,v 的最小生成樹 假設集合u裡面存放的是已經在最小生成樹中的頂點,集合te存放的是最小生成樹的邊,演算法從u 開始,在所有u u,v v u的所有邊 u,v 中選一條...
資料結構 最小生成樹
生成樹 乙個連通圖的最小連通子圖稱作該圖的生成樹。有n個結點的連通圖的生成樹有n個結點和n 1條邊。乙個有n個結點的連通圖的生成樹是原圖的極小連通子圖,它包含原圖中的所有n個結點,並且有保持圖連通的最少的邊。由生成樹的定義可知 若在生成樹中刪除一條邊,就會使該生成樹因變成非連通圖而不再滿足生成樹的定...
資料結構(最小生成樹)
對於乙個無相連通網,他的所有生成樹中必有一棵邊的權值總和最小的生成樹,稱之為最小代價生成樹,簡稱最小生成樹。最小生成樹必須滿足三個條件 1 構造的最小生成樹必須包括n個頂點 2 構造的最小生成樹有且僅有n 1條邊 3 構造的最小生成樹中不存在迴路。普利姆演算法 prim 假設g v,e 為一無向連通...