目录:
- 介绍:
- 代码:
- 分析:
- 汇编:
介绍:
一个有 n 个结点的连通图的生成树是原图的极小连通子图,且包含原图中的所有 n 个结点,
并且有保持图连通的最少的边。
最小生成树可以用kruskal(克鲁斯卡尔)算法或prim(普里姆)算法求出
普利姆算法,图论中一种算法,可在加权连通图里搜索最小生成树。
此算法搜索到的边子集所构成的树中,不但包括连通图里的所有顶点,且所有边的权值最小
代码:
#include <stdio.h>
#include <stdlib.h>/*
程序描述:
矩阵有多行数据,cost数组从矩阵中提取数据,P记录cost数组的数据分别属于矩阵的哪一行
Mark记录在cost不再进行比较数据的下标(已经是最小值当前cost中最小值的下标了)
在cost数组中找出最小值与其在cost中的下标,再将该下标在mark中标记,下次不再处理这个位置
当前cost比较完成后,用找到的最小值作为下一行要提取数据的行号,然后用该行的数据与cost中的数据
比较,取每个位置较小值,除了已经标记的位置不进行提取。并修改P中对应较小值属于行
更新cost和P后,再进行在cost中找最小值同样的操作,依次循环整个矩阵
*/#define VNUM 9
#define MV 65536int P[VNUM];//存储要当前比较的数据是属于哪一行的
int Cost[VNUM];//要用于比较的数据的数组
int Mark[VNUM];//记录列状态,标记为1的列,将不再处理比较
int Matrix[VNUM][VNUM] = //n行与n列数据一样的矩阵
{{0, 10, MV, MV, MV, 11, MV, MV, MV},{10, 0, 18, MV, MV, MV, 16, MV, 12},{MV, 18, 0, 22, MV, MV, MV, MV, 8},{MV, MV, 22, 0, 20, MV, MV, 16, 21},{MV, MV, MV, 20, 0, 26, MV, 7, MV},{11, MV, MV, MV, 26, 0, 17, MV, MV},{MV, 16, MV, MV, MV, 17, 0, 19, MV},{MV, MV, MV, 16, 7, MV, 19, 0, MV},{MV, 12, 8, 21, MV, MV, MV, MV, 0},
};
//cost 先取第一行的数据开始比较
void Prim(int sv) // O(n*n)
{int i = 0;int j = 0;if( (0 <= sv) && (sv < VNUM) )//判断sv在矩阵范围内{for(i=0; i<VNUM; i++){Cost[i] = Matrix[sv][i];//将sv行所有列赋到cost,表示从sv行的数据开始处理比较P[i] = sv;//将P全部赋0,表示当前所有数据属于0行的Mark[i] = 0;//Mark数组全赋0,初始化}Mark[sv] = 1;//将0列设为1,刚开始0列不处理比较for(i=0; i<VNUM; i++){int min = MV;int index = -1;for(j=0; j<VNUM; j++){//从没有被标记数据中取值,找出cost(当前要比较的数据)中最小值和其在cost中的下标if( !Mark[j] && (Cost[j] < min) ){min = Cost[j];//给最小值赋值 index = j;//最小值的下标 }}if( index > -1 )//表示执行了上面,找到了最小值{Mark[index] = 1; //将该下标进行标记,下次不再比较该列的数据printf("(%d, %d, %d)\n", P[index], index, Cost[index]); // 输出这次查找出最小值位于的行与下标与数值}for(j=0; j<VNUM; j++) //循环找出下一次用比较的数据{//从上次找到的最小值的下标,作为重新提取数据的行//只要不是被标记的列,从行中提取的数据比原来比较的数据小就取行中的数和下标//也用新的一行中的数据与本来用于比较的数据取对应位置较小的一方,并将该位置的值属于//哪一行中提取出来的,存到P中if( !Mark[j] && (Matrix[index][j] < Cost[j]) ) //更新到cost数组{Cost[j] = Matrix[index][j];//更新用来比较数据数组P[j] = index;//更新数据属于的行}}}}
}int main(int argc, char *argv[])
{Prim(0);getchar();return 0;
}
分析:
汇编: