最小生成树(Prim算法)笔记

引言:

一开始用起始点初始化adjvex数组,表示是起始点到各个顶点, 当有一个顶点P加入生成树,并且这个顶点到另一个顶点Q的权值小于lowcost[]数组中的,则说明生成树到另一个顶点Q的最短路径是通过P顶点,所以更新adjvex[Q]=P,  这就是为什么这样更新adjvex[]数组。

对于一个带权连通无向图 G=(V,  E),边的权值之和最小的生成树,称之为最小生成树.

Prim算法时间复杂度为: O(V^2) 复杂度是顶点的平方,所以Prim算法适用于稠密图.

Prim算法操作步骤:        Prim算法是先指定一个源点,将源点添加到生成树集合,找到生成树集合中元素到非生成树与那是中权值最小的顶点,将这个顶点添加到生成树集合中,并且更改生成树中辅助数组,之后再找从生成树到非生成树中权值最小的顶点,加入到生成树集合,更新辅助数组,往复操作,直到最后一个顶点都加入到生成树

最小生成树是在图 (邻接矩阵) 中选择出一个权值累加和最小的树,所以自己首先需要构建一个图(邻接矩阵)。如:   v0 --> v2 = ∞,说明v0到v2这两个结点没有边  v0-->v0=0,说明是自身结点 v1->v0=10,表示v1->v0结点的权重为10。 

Prim算法,即每次选择生成树顶点到非生成树顶点最小的权值,然后辅助数组,更新权值,如此反复,保证每次最优来达到最优解。

思路:

1给定以顶点v开始,  现在用v来初始化辅助数组shortEdge,

2.给定起始结点v,从v结点开始生成树. 首先将v结点加入生成树.并打印信息

3.之后进入循环n-1次循环,因为n个顶点,v结点已经加入生成树了,所以在循环中会少一个结点加入生成树.

4.在辅助数组中找到生成树到邻接顶点权值最小的边,邻接顶点编号记为k,

5.打印出选择出来的结点信息和权值信息

6.将找到的结点加入到生成树中,

7. 更新辅助数组shortEdge的信息。让arc[k][j]去更新lowcost[j], 如果arc[k][j]比lowcost[]的权值更小,则说明从k到达j顶点的权值 更小, 让adjvex[j]=k;adjvex[]数组存放的就是到达顶点最小的顶点。

结点信息:

class node{
	public:
		int adjvex;    //保存邻接点的下标 如 adjvex[2]=3;   j->k权值小
		int lowcost;   
};

class MST{
	public:
		node shortEdge[MAXSIZE];  //这是一个辅助数组,
};

adjvex[]={0,0,1,0,0,0,1,0,1}表示到达2,6,8 v1->2,6,8这几个顶点的权值更小.

开始生成树

adjvex[]数组存放的是生成树到非生成树结点权值最小的边

1. 初始化数组,adjvex[] 和lowcost[] 数组,lowcost[start]=0表示v0加入生成树中,  adjvex[start]=3,表示是从v3->start边,,想想用起始点初始化,adjvex[i]=start, 说明是start到其他所有顶点。

2. 将start元素添加到生成树中, 并且输出这个点的信息,

3.开始n-1趟遍历, 首先找到非生成树顶点权值最小的边,得到那条边的顶点的索引,输出这个顶点信息,并且将这个顶点添加到生成树集合中, 

4.开始n-1趟遍历,除自身顶点外还有n-1个顶点,比较新加入顶点到各个非生成树顶点的权值,如果该顶点到非生成树顶点的权值小于lowcost[]记录的权值,则更新lowcost[j]=arc[k][j], (更新lowcost[]的目的是用来比较生成树顶点到其他顶点的权值,所以lowcost值越来越小),并且将下标为k的顶点存入adjvex, 即adjvex[j] =k;

int sum=0;
void prim(MGraph G,int start){
	
	//初始化shortEdge[]数组
	for(int i=0; i<G.vertexNum; i++){
		shortEdge[i].lowcost = G.arc[start][i];
		shortEdge[i].adjvex = start;
	} 
	
	//起点start加入U集合 
	shortEdge[start].lowcost=0;
	
    for(int i=0; i<G.vertexNum-1; i++){

        //在shortEdge[]中找到不在生成树顶点的权值最小的邻接点
		k = minEdge(shortEdge,G.vertexNum);  

        //输出顶点k和对应的权值
        cout<<shortEdge[k].adjvex<<" "<<shortEdge[k].lowcost<<endl;   
		
        shortEdge[k].lowcost=0;     //表示k结点加入生成树

        判断新加入的顶点到各个边的权值是不是比之前生成树的权值小,现在新顶点已经加入了,
        如果新加入顶点权值比生成树权值小,就相当于更新生成树权值
		for(int j=1; j<G.vertexNum; j++){  除去自身顶点,所以遍历vertexNum-1次
			if(lowcost[j]!=0 && G.arc[k][j]<shortEdge[j].lowcost){
			    shortEdge[j].lowcost = G.arc[k][j];
                shortEdge[j].adjvex = k;
             }
		} 
	}
}

 在shortEdge辅助数组中找到权值最小的并返回

//找一维数组中最小权值的索引
const int INF = 56537
int minEdge(node shortEdge,int x){   //x表示图中顶点数目,遍历shortEdge数组
    int min = INF;    
    for(int j=1; j<x; j++){     //除去自身顶点还剩vertexNum-1个顶点
        if(shortEdge[j].lowcost!=0 && shortEdge[j].lowcost<min){
            min = shortEdge[j].lowcost;
            k = j;
        }
    }
    return k;      //得到最小权值的索引
}

每次都在shortEdge数组中查询,找最小的权值,(必须是没有加入生成树的结点 )
当有一个结点加入生成树时候,就更新shortEdge的两个值,

 输出如何是如何生成树的:

//在未加入生成树结点中找到权值最小边的结点索引
int MinEdge(int lowcost[], int vertexNum)
{
	int min=INF;
	int loc;
	for(int i=0; i<vertexNum; i++){
		if(lowcost[i]!=0 && lowcost[i]<min){
			min = lowcost[i];
			loc = i;
		}
	}
	
	return loc;

}

//找到到某顶点最小边,是哪个顶点到某顶点边最小
int MaxEdge(int lowcost[], int vertexNum, int adjvex[]){
	int min = INF;
	int loc;
	
	//在未加入的顶点中找,到最小的边的索引i, 索引的adjvex[i]存储的是哪个顶点到i顶点的信息。 
	for(int i=0; i<vertexNum; i++){
		if(lowcost[i]!=0 && lowcost[i]<min){
			min = lowcost[i];
			loc = adjvex[i];
		}
	}
	return loc;
} 

        int k = MinEdge(lowcost,vertexNum);
		int m = MaxEdge(lowcost,vertexNum,adjvex);
		cout<<vertex[m]<<" "<<vertex[k]<<" "<<lowcost[k]<<endl;
        
        输出每步生成树的起始顶点,终顶点,和这条边的权值.

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
逻辑结构:描述数据元素之间的逻辑关系,如线性结构(如数组、链表)、树形结构(如二叉树、堆、B树)、图结构(有向图、无向图等)以及集合和队列等抽象数据类型。 存储结构(物理结构):描述数据在计算机中如何具体存储。例如,数组的连续存储,链表的动态分配节点,树和图的邻接矩阵或邻接表表示等。 基本操作:针对每种数据结构,定义了一系列基本的操作,包括但不限于插入、删除、查找、更新、遍历等,并分析这些操作的时间复杂度和空间复杂度。 算法算法设计:研究如何将解决问题的步骤形式化为一系列指令,使得计算机可以执行以求解问题。 算法特性:包括输入、输出、有穷性、确定性和可行性。即一个有效的算法必须能在有限步骤内结束,并且对于给定的输入产生唯一的确定输出。 算法分类:排序算法(如冒泡排序、快速排序、归并排序),查找算法(如顺序查找、二分查找、哈希查找),图论算法(如Dijkstra最短路径算法、Floyd-Warshall算法、Prim最小生成树算法),动态规划,贪心算法,回溯法,分支限界法等。 算法分析:通过数学方法分析算法时间复杂度(运行时间随数据规模增长的速度)和空间复杂度(所需内存大小)来评估其效率。 学习算法与数据结构不仅有助于理解程序的内部工作原理,更能帮助开发人员编写出高效、稳定和易于维护的软件系统。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值