Prim算法

Prim算法又称为加边法,即每次选择最小权值的边加入到生成树中,然后再更新权值,如此反复,保证每次最优来达到最优解。特点是时刻维护一棵树,算法不断加边,加的过程始终是一棵树

节点结构

1.图的结点结构

        图的顶点集

        图的邻接矩阵

        顶点个数

        边的个数

2.结构体数组

 

        adjvex---代表到当前下标的顶点

        lowcost---代表到当前下标顶点的权值

Prim

我们把节点分为两大块;一块是最小生成树的节点,一块是尚未处理的节点

通过将shortEdge[i].lowcost的值赋为0来标识该点已加入最小生成树之中

具体过程:

        先将选好的start节点的邻接矩阵的值初始化给shortEdge数组

        再将start节点放在最小生成树的那一块(shortEdge[start].lowcost=0;)

        再遍历剩下是节点;寻找此时shortEdge数组(在尚未处理的节点中寻找,即shortEdge[i].lowcost!=0)的最小lowcost,将该下标赋值给k

        打印路径及权值

        然后遍历start这个点的邻接矩阵,如果邻接矩阵的值更小,就更新shortEdge的lowcost,再更新adjvex即新的最短路的点

#include<iostream>
#include<string.h>
#define mymax 65535
using namespace std;
typedef struct Graph
{
	int* spot;//点集
	int** line;//邻接矩阵
	int spotNum;
	int lineNum;
}Graph;
Graph* initGraph(int dianshu)
{
	Graph* G = new Graph;
	G->spotNum = dianshu;
	G->lineNum = 0;
	G->spot = new int[dianshu];
	G->line = new int* [dianshu];
	for (int i = 0; i < dianshu; i++)
	{
		G->line[i] = new int[dianshu];
	}
	return G;
}
void createGraph(Graph* G, int* dian, int* bian)
{
	for (int i = 0; i < G->spotNum; i++)
	{
		G->spot[i] = dian[i];
		for (int j = 0; j < G->spotNum; j++)
		{
			G->line[i][j] = bian[j + i * G->spotNum];
			if (G->line[i][j] != 0)
			{
				G->lineNum++;
			}
		}
	}
	G->lineNum /= 2;
}
typedef struct arry
{
	int adjvex;//通过其值到当前下标顶点
	int lowcost;//当前生成树到其他顶点的值
}arry;
arry* initShortEdge(int dianshu)//初始化shortEdge数组
{
	arry* shortEdge = new arry[dianshu];
	for (int i = 0; i < dianshu; i++)
	{
		shortEdge[i].adjvex = 0;
		shortEdge[i].lowcost = 0;
	}
	return shortEdge;
}
int minEdge(arry* shortEdge, int dianshu)
{
	int min = 65535;
	int k;
	for (int i = 0; i < dianshu; i++)
	{
		if (shortEdge[i].lowcost != 0 && shortEdge[i].lowcost < min)
		{
			min = shortEdge[i].lowcost;
			k = i;
		}
	}
	return k;
}
void outputSMT(int k, arry* shortEdge)
{
	cout << "(" << shortEdge[k].adjvex << "," << k << ")" << " " << shortEdge[k].lowcost << endl;
}
void Prim(Graph* G, int start)
{
	arry* shortEdge = initShortEdge(G->spotNum);
	for (int i = 0; i < G->spotNum; i++)
	{
		shortEdge[i].lowcost = G->line[start][i];//通过start值到当前下标顶点的权值
		shortEdge[i].adjvex = start;//通过start到当前下标顶点
	}
	shortEdge[start].lowcost = 0;//将当前start节点加入最小生成树集合中
	for (int i = 0; i < G->spotNum - 1; i++)//第一个顶点不需要遍历
	{
		int k = minEdge(shortEdge, G->spotNum);//寻找最短边的邻接点
		outputSMT(k, shortEdge);
		shortEdge[k].lowcost = 0;//将顶点k加入到最小生成树
		for (int j = 0; j < G->spotNum; j++)
		{
			if (G->line[k][j] < shortEdge[j].lowcost)
			{
				shortEdge[j].lowcost = G->line[k][j];
				shortEdge[j].adjvex = k;
			}
		}
	}

}
void printLine(Graph* G)
{
	for (int i = 0; i < G->spotNum; i++)
	{
		for (int j = 0; j < G->spotNum; j++)
		{
			cout << G->line[i][j] << "\t";
		}
		cout << endl;
	}
	cout << endl;
}
void printSpot(Graph* G)
{
	for (int i = 0; i < G->spotNum; i++)
	{
		cout << G->spot[i] << "\t";
	}
	cout << endl;
}
int main()
{
	int array[] = { 0,1,2,3,4,5 };
	int dianshu = sizeof(array) / sizeof(int);
	Graph* G = initGraph(dianshu);
	int bian[] = { 0,34,46,mymax,mymax,19,
				  34,0,mymax,mymax,12,mymax,
				  46,mymax,0,17,mymax,25,
				  mymax,mymax,17,0,38,25,
				  mymax,12,mymax,38,0,26,
				  19,mymax,25,25,26,0 };
	createGraph(G, array, bian);
	int start;
	cout << "请输入从哪一个顶点出发:";
	cin >> start;
	cout << endl;
	cout << "点集:" << endl;
	printSpot(G);
	cout << endl;
	cout << "邻接矩阵:" << endl;
	printLine(G);
	cout << "路径:" << endl;
	Prim(G, start);

}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值