您的位置:首页 > 编程语言

算法分析与设计作业一之Prim算法和Kruskal算法的图解及代码实现

2020-03-10 00:40 309 查看

Prim算法:
一、问题描述:
在带权连通图中V是包含所有顶点的集合,U是已经在最小生成树中的节点。开始时,从图中任意某一顶点v开始,此时集合U={v}(以v到其他顶点的所有边为侯选边);在所有u∈U,w∈V-U的边(u,w)∈E中找到一条权值最小的边,将(u,w)这条边加入到已找到边的集合,并且将点w加入到集合U中,重复上一操作,当U=V时,就找到了这颗最小生成树。

二、算法核心步骤(伪代码)及图解:
(1) 定义min存取最小权值,lowcost[]、adjvex[]分别存权值和顶点下标;
(2) For循环遍历所有与v0相邻的边,并初始化全部顶点为v0下标;
(3) 初始化最小权值为最大的不可能值,遍历全部顶点,找到最小权值;
(4) 打印当前顶点边中权值最小的边,邻接矩阵逐个遍历全部顶点,将较小的权值存入lowcost[],将下标为k的顶点存入adjvex中。

三、代码实现:

#include <stdio.h>
#define MAXVEX 10
#define TRUE 1
#define FALSE 0
#define Maxweight 65535//此处是权值极最大值
#define LENGTH(a) (sizeof(a) / sizeof(a[0]))

typedef char VertexType;
typedef struct
{
VertexType vexs[MAXVEX];    //存储顶点信息
int arc[MAXVEX][MAXVEX];    //邻接矩阵
int numVertexes, numEdges;  //边数和点数
}MGraph;

void createMGraph(MGraph *G)     // 创建图
{
int i, j;

printf("请输入边数和顶点数:");
scanf("%d %d",&G->numEdges,&G->numVertexes);
//G->numEdges=10;
//G->numVertexes=6;

for (i = 0; i < G->numVertexes; i++)    // 初始化图
{
for ( j = 0; j < G->numVertexes; j++)
{
if (i==j)
G->arc[i][j]=0;
else
G->arc[i][j] = G->arc[j][i] = Maxweight;
}
}

G->arc[0][1]=6;
G->arc[0][2]=1;
G->arc[0][3]=5;
G->arc[1][2]=5;
G->arc[1][4]=3;
G->arc[2][3]=7;
G->arc[2][4]=5;
G->arc[2][5]=4;
G->arc[3][5]=2;
G->arc[4][5]=6;

for(i = 0; i < G->numVertexes; i++)
{
for(j = i; j < G->numVertexes; j++)//注意 这里j的起点是从i开始的
{
G->arc[j][i] =G->arc[i][j];//因为是无向图 所以顶点具有对称性
}
}

}

//Prim 算法生成最小生成树
void Prim(MGraph G)
{
int min, i, j, k;
int lowcost[MAXVEX];   // 权值
int adjvex[MAXVEX];   // 顶点的下标
lowcost[0] = 0;       //v0权值为0
adjvex[0] = 0;        // v0第一个加入
for(i = 1; i < G.numVertexes; i++)
{
lowcost[i] = G.arc[0][i];  // 遍历所有与v0相邻的边
adjvex[i] = 0;             // 初始化全部先为 v0 的下标
}
for(i = 1; i < G.numVertexes; i++)
{
min = Maxweight;   // 初始化最小权值为最大的不可能值
j = 1;
k = 0;
while(j < G.numVertexes)  // 遍历全部顶点
{
if(lowcost[j] != 0 && lowcost[j] < min)
{
min = lowcost[j];
k = j;
}
j++;
}
lowcost[k] = 0;  // 将当前顶点的权值设置为0
printf("(%d, %d)", adjvex[k], k);  // 打印当前顶点边中权值最小的边
//邻接矩阵k行逐个遍历全部顶点
for(j = 1; j < G.numVertexes; j++)
{
if(lowcost[j] != 0 && G.arc[k][j] < lowcost[j])
{
lowcost[j] = G.arc[k][j];  // 将较小的权值存入 lowcost 相应位置
adjvex[j] = k;   // 将下标为 k 的顶点存入 adjvex
}
}
}
}

int main()
{
MGraph G;
createMGraph(&G);
Prim(G);
return 0;
}

四、Prim算法时间复杂度分析:
顶点数为v,边数为e,邻接矩阵复杂度为:O(v^2) 邻接表:O(elog2 v);

Kruskal算法:
一、问题描述:
在带权连通图中V是包含所有顶点的集合,U是已经在最小生成树中的节点。开始时,对图中所有权值进行排序,找到最小的权值所在边,将这条边所连接的两端点放入集合U,重复上一操作,当找到n-1条边时,就找到了这颗最小生成树。

二、算法核心步骤(伪代码)及图解:
(1)新建图G,G中拥有原图中相同的节点,但没有边;
(2)将原图中所有的边按权值从小到大排序;
(3)从权值最小的边开始,如果这条边连接的两个节点于图G中不在同一个连通分量中,则添加这条边到图G中;
(4)重复3,直至图G中所有的节点都在同一个连通分量中。

三、代码实现:

#include <stdio.h>
#define MAXVEX 10
#define TRUE 1
#define FALSE 0

typedef struct{
int vertex1;        //存储边的起始顶点
int vertex2;        //存储边的终止顶点
int weight;         //权值
}Edge;

int kruskal(Edge Edges[],int n,int e)
{
int i,j,v1,v2,a1,a2,k;
int a[n+1];
for(i=1;i<=n;i++)
a[i]=i;
k=1;
j=0;                     //下标初值为0
while(k<e)               //生成的边数小于e时继续循环
{
v1=Edges[j].vertex1;
v2=Edges[j].vertex2; //取一条边的两个邻接点
a1=a[v1];
a2=a[v2];
if(a1!=a2)    //防止出现闭合回路
{
printf("(%d,%d)\n",v1,v2);

k++;                //生成边数增加
if(k>=n)
break;
for(i=1;i<=n;i++)
if (a[i]==a2)
a[i]=a1;
}
j++;
}
}

int sort(Edge arr[],int low,int high)
{
int key;
Edge min;
min=arr[low];
key=arr[low].weight;
while(low<high)
{
while(low<high && arr[high].weight>=key)
high--;
if(low<high)
arr[low++]=arr[high];

while(low<high && arr[low].weight<=key)
low++;
if(low<high)
arr[high--]=arr[low];
}
arr[low]=min;
return low;
}

void quick_sort(Edge arr[],int start,int end)
{
int pos;
if(start<end)
{
pos=sort(arr,start,end);
quick_sort(arr,start,pos-1);
quick_sort(arr,pos+1,end);
}
}

int main()
{
Edge Edges[MAXVEX];
int numEdges,numVertexes;
printf("输入顶数和边数:\n");
scanf("%d%d",&numVertexes,&numEdges);
for(int i=0;i<numEdges;i++)
{
scanf("%d%d%d",&Edges[i].vertex1,&Edges[i].vertex2,&Edges[i].weight);
}
quick_sort(Edges,0,numEdges-1);
kruskal(Edges,numVertexes,numEdges);
}

四、Kruskal算法时间复杂度分析:
平均时间复杂度为O(|E|log|E|),其中E和V分别是图的边集和点集。

  • 点赞
  • 收藏
  • 分享
  • 文章举报
littleshi00 发布了2 篇原创文章 · 获赞 0 · 访问量 26 私信 关注
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐