程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> 關於C語言 >> 數據結構(C實現)------- 最小生成樹之Prim算法

數據結構(C實現)------- 最小生成樹之Prim算法

編輯:關於C語言

數據結構(C實現)------- 最小生成樹之Prim算法


 

算法描述

  如果連通圖是一個網,則稱該網中所有生成樹中權值總和最小的生成樹為最小生成樹,也稱最小代價生成樹。利用Prim算法構造的最小生成樹方法思想:

  假設G=(V,E)是一個具有n個頂點的連通網,頂點集V={v1,v2,...,vn}.設所求的最小生成樹T=(U,TE),其中U是T的頂點集,TE是T的邊集,U和TE初值均為空集。

  Prim算法的基本思想如下:首先從V中任取一個頂點(假定取v1),將生成樹T置為僅有一個結點v1的樹,即U={v1};然後只要U是V的真子集,就在所有那些一個端點在T中,另一個端點在T外的邊中,找一條最短(即權值最小 )的邊。假定符合條件的最短邊為(vi,vj),則把該條邊和其不在T中的頂點vj,分別並入T的邊集TE和頂點集U。如此進行下去,每次往生成樹裡並入一個頂點和一條邊,直到把所有頂點都包括進生成樹T為止。此時,必有U=V,TE中有n-1條邊,則T=(U,TE)是G的一棵最小生成樹。

算法實現

  設一個edge數組,記錄從頂點U集到V-U的代價最小的邊,每條邊的信息包括邊的始點和,終點和權值。從頂點u出發,利用prim算法求最小生成樹步驟如下:

  (1) 初始化edge數組,記錄頂點u到圖中其余結點的代價最小的n-1的邊。

  (2) 將頂點u加入U中。

  (3) 當U不等於V時,做如下處理。

    1) 從edge數組中選一條代價最小的邊。

    2) 將該邊的終點加入U中。

    3) 調整edges數組,使它始終記錄頂點U到V-U的代價最小的邊。

算法代碼

 

// 定義邊結構體
typedef struct{
	int start;
	int end;
	int cost;
}Edge;


/* 
 *Prim算法求最小生成樹
 * */
void Prim_MG(MGraph MG,char vs){
	Edge edge[MAX_VEX_NUM];
	int i,j,k,v,min;
	int s = getIndexOfVexs(vs,&MG);
	//初始化邊
	for(i = 1;i <= MG.vexnum;i++){
		if(s != i){
			edge[i].start = s;
			edge[i].end = i;
			edge[i].cost = MG.arcs[s][i];
		
		}
	}
	//首先將s加入生成樹集合中
	edge[s].cost = 0;
	for(i = 2;i <= MG.vexnum;i++){
		min = 1000;
		for(j = 1;j<= MG.vexnum;j++){
			if(edge[j].cost != 0 && edge[j].cost < min ){
				min = edge[j].cost;
				k = j;
			}
		}
		v = edge[k].end;
		edge[v].cost = 0; // 加入新節點

		//輸出生成樹中的邊
	 	printf(%c %c %d
,MG.vexs[edge[v].start],MG.vexs[edge[v].end],MG.arcs[edge[v].start][edge[v].end]);

		//重新調整數組
		for(j = 1;j <= MG.vexnum;j++){
			if(edge[j].cost != 0 && MG.arcs[v][j] != 0 && MG.arcs[v][j] < edge[j].cost){
				edge[j].start = k;
				edge[j].end = j;
				edge[j].cost = MG.arcs[v][j];
			}
		}
	}

}

 

算法說明

  假設圖中有n個頂點,則第一個進行初始化的循環語句的頻度為n,第二個循環語句頻度為n-1。其中有兩個內循環;其一是在edge數組中找權值最小的邊,其頻度為n-1,其二是重新調整edge數組的邊,頻度為n,所以Prim算法的時間復雜度為O(n^2),而與圖中的邊數無關,因此適用於求稠密的最小生成樹。

 

完整代碼

 

/*
 * =====================================================================================
 *
 *       Filename:  Prim.c
 *
 *    Description:  最小生成樹算法之Prim算法 
 *
 *        Version:  1.0
 *        Created:  2015年03月11日 15時27分19秒
 *       Revision:  none
 *       Compiler:  gcc
 *
 *         Author:  jesson20121020 (), [email protected]
 *   Organization:  
 *
 * =====================================================================================
 */

#include 
#include 
#define MAX_VEX_NUM 50
#define UN_REACH 1000




typedef char VertexType;
typedef enum {
	DG, UDG
} GraphType;
typedef struct {
	VertexType vexs[MAX_VEX_NUM];
	int arcs[MAX_VEX_NUM][MAX_VEX_NUM];
	int vexnum, arcnum;
	GraphType type;
} MGraph;



/**
 * 根據名稱得到指定頂點在頂點集合中的下標
 * vex  頂點
 * return 如果找到,則返回下標,否則,返回0
 */
int getIndexOfVexs(char vex, MGraph *MG) {
	int i;
	for (i = 1; i <= MG->vexnum; i++) {
		if (MG->vexs[i] == vex) {
			return i;
		}
	}
	return 0;
}

/**
 * 創建鄰接矩陣
 */
void create_MG(MGraph *MG) {
	int i, j, k,weight;
	int v1, v2, type;
	char c1, c2;
	printf(Please input graph type DG(0) or UDG(1) :);
	scanf(%d, &type);
	if (type == 0)
		MG->type = DG;
	else if (type == 1)
		MG->type = UDG;
	else {
		printf(Please input correct graph type DG(0) or UDG(1)!);
		return;
	}

	printf(Please input vexmun : );
	scanf(%d, &MG->vexnum);
	printf(Please input arcnum : );
	scanf(%d, &MG->arcnum);
	getchar();
	for (i = 1; i <= MG->vexnum; i++) {
		printf(Please input %dth vex(char):, i);
		scanf(%c, &MG->vexs[i]);
		getchar();
	}

	//初始化鄰接矩陣
	for (i = 1; i <= MG->vexnum; i++) {
		for (j = 1; j <= MG->vexnum; j++) {
			if(i == j)
				MG->arcs[i][j] = 0;
			else
				MG->arcs[i][j] = UN_REACH;
		}
	}

	//輸入邊的信息,建立鄰接矩陣
	for (k = 1; k <= MG->arcnum; k++) {
		printf(Please input %dth arc v1(char) v2(char) weight(int): , k);

		scanf(%c %c %d, &c1, &c2,&weight);
		v1 = getIndexOfVexs(c1, MG);
		v2 = getIndexOfVexs(c2, MG);
		if (MG->type == 1)
			MG->arcs[v1][v2] = MG->arcs[v2][v1] = weight;
		else
			MG->arcs[v1][v2] = weight;
		getchar();
	}




}
/**
 * 打印鄰接矩陣和頂點信息
 */
void print_MG(MGraph MG) {
	int i, j;
	if(MG.type == DG){
		printf(Graph type: Direct graph
);
	}
	else{
		printf(Graph type: Undirect graph
);
	}

	printf(Graph vertex number: %d
,MG.vexnum);
	printf(Graph arc number: %d
,MG.arcnum);

	printf(Vertex set:
 );
	for (i = 1; i <= MG.vexnum; i++)
		printf(%c	, MG.vexs[i]);
	printf(
Adjacency Matrix:
);

	for (i = 1; i <= MG.vexnum; i++) {
		j = 1;
		for (; j < MG.vexnum; j++) {
			printf(%d	, MG.arcs[i][j]);
		}
		printf(%d
, MG.arcs[i][j]);
	}
}


// 定義邊結構體
typedef struct{
	int start;
	int end;
	int cost;
}Edge;


/* 
 *Prim算法求最小生成樹
 * */
void Prim_MG(MGraph MG,char vs){
	Edge edge[MAX_VEX_NUM];
	int i,j,k,v,min;
	int s = getIndexOfVexs(vs,&MG);
	//初始化邊
	for(i = 1;i <= MG.vexnum;i++){
		if(s != i){
			edge[i].start = s;
			edge[i].end = i;
			edge[i].cost = MG.arcs[s][i];
		
		}
	}
	//首先將s加入生成樹集合中
	edge[s].cost = 0;
	for(i = 2;i <= MG.vexnum;i++){
		min = 1000;
		for(j = 1;j<= MG.vexnum;j++){
			if(edge[j].cost != 0 && edge[j].cost < min ){
				min = edge[j].cost;
				k = j;
			}
		}
		v = edge[k].end;
		edge[v].cost = 0; // 加入新節點

		//輸出生成樹中的邊
	 	printf(%c %c %d
,MG.vexs[edge[v].start],MG.vexs[edge[v].end],MG.arcs[edge[v].start][edge[v].end]);

		//重新調整數組
		for(j = 1;j <= MG.vexnum;j++){
			if(edge[j].cost != 0 && MG.arcs[v][j] != 0 && MG.arcs[v][j] < edge[j].cost){
				edge[j].start = k;
				edge[j].end = j;
				edge[j].cost = MG.arcs[v][j];
			}
		}
	}

}

/**
 * 主函數
 */
int main(void) {
	MGraph MG;
	char startVex;
	create_MG(&MG);
	print_MG(MG);

	printf(
Please input the start vex(char):);
	scanf(%c,&startVex);
	printf(
The result of Prim:
);
	Prim_MG(MG,startVex);	
	
	return EXIT_SUCCESS;
}

 

 

運行演示

 

 

jesson@jesson-HP:~/develop/workspace/c_learning/csdn/Prim$ gcc -o Prim Prim.c
jesson@jesson-HP:~/develop/workspace/c_learning/csdn/Prim$ ./Prim 
Please input graph type DG(0) or UDG(1) :1
Please input vexmun : 4
Please input arcnum : 5
Please input 1th vex(char):a
Please input 2th vex(char):b
Please input 3th vex(char):c
Please input 4th vex(char):d
Please input 1th arc v1(char) v2(char) weight(int): a b 1
Please input 2th arc v1(char) v2(char) weight(int): a c 3
Please input 3th arc v1(char) v2(char) weight(int): a d 4
Please input 4th arc v1(char) v2(char) weight(int): b c 2
Please input 5th arc v1(char) v2(char) weight(int): c d 3

Please input the start vex(char):a

The result of Prim:
a b 1
b c 2
c d 3


 

 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved