最小生成树的算法

17 篇文章 0 订阅
14 篇文章 0 订阅
//邻接矩阵
typedef struct
{
	int no;//顶点信息
	char info;
}VertexType;
typedef struct
{
	int edges[MAX_Size][MAX_Size];//存放边的关系
	char  vex[MAX_Size];//存放顶点的值
	int n ,e;//分别为顶点数目和边的数目
}MGrap;


//建立有向图的邻接矩阵表示
void createGrap(MGrap *g)
{
	
	cout <<"请输入顶点数和边的数"<<endl;
	cin>>g->n>>g->e;
	cout<<"请输入顶点信息"<<endl;
	for (int i =0;i<g->n;i++)
	{
		cin>>g->vex[i];
	}
	//初始化矩阵
	for (int i =0;i<g->n;i++)
	{
		for (int j =0;j<g->n;j++)
		{
			g->edges[i][j] = 0;
		}
	}
	cout<<"请输入边的信息:起始边和终止边"<<endl;
	for (int i =0;i<g->e;i++)
	{
		int start, end;
		cin>>start>>end;
		g->edges[start][end] = 1;
	}
}

 

 

//最小生成树之prim算法。
/*
算法思想:
从图中某个顶点V0开始,构造生成树的算法如下。
1)将V0到其他顶点的所有边当做候选边,
2)重复以下步骤n-1次,使得其他n-1个顶点被并入到生成树当中
	A.从候选边中选择权值最小的边输出,并将于该边另一端相接的顶点vi并入生成树中
	B.考察所有剩余顶点,如果(v,vi)的权值比lowcost[vi]更小,则用更小的权值更新lowcost[vi]

*/
void prim(MGrap *g,int v ,int &sum)
{
	int lowcost[MAX_Size]={0};
	int vset[MAX_Size] ={0};
	int min = 65535;//如果这个值比6635大,说明这两点没有连接
	int index = 0;
	//选择一个顶点,作为第一个数的顶点 并计算该点到其余顶点的权值。
	for (int i =0;i<g->n;i++)
	{
		lowcost[i] = g->edges[v][i];	
	}
	vset[v]=1;//将顶点v并入树中
	for (int i =0;i<g->n-1;i++)//选择n-1个顶点并入树中
	{
	for (int j =0;j<g->n;j++)//选择最小权值的边
	{
		if (vset[j]==0&&min>lowcost[j])
		{
			min = lowcost[j];
			index =j;//选择没有被并入树并且权值最小的边的顶点
		}
		
	}
	vset[index] =1;
	sum+= min;
	//这里要做说明的是lowcost中存的是除了当前新加入节点之外,到没有并入到树中的节点的最短距离,
	//因而,我们只需要找到新并入节点到没有并入树中的其他顶点的最小权值就行了
	for (int j=0;j<g->n;j++)
	{
		if (vset[j]==0&&g->edges[index][j]<lowcost[j])
		{
			lowcost[j] = g->edges[index][j];
		}
	}
		
	}
}
//克鲁斯卡尔算法:,每次选最小的且和已经有的树不形成环的边作为生成树的边。
//算法实现
typedef struct
{

	int a,b;
	int w;
}Road;

Road road[MAX_Size];//定义边集
int v[MAX_Size];//定义并查集
int getRoot(int a)
	{
		while(a!= v[a]) 
		a= v[a];
		return a;
	}
bool compare(Road r1,Road r2)
{
	if (r1.w<r2.w)
	{
		return true;//从小到大排序
	}
}

void mysort(Road *road,int E)
{
	vector<Road> v;
	for (int i =0;i<E;i++ )
	{
		v.push_back(road[i]);
	}
	sort(v.begin(),v.end(),compare);
}

 

void  Kruskal(MGrap g,int & sum,Road *road)
{
	int N = g.n;
	int E = g.e;
	for (int i=0;i<N;i++)
	{
		v[i] =i;
	}
	mysort(road,E);//排序
	for (int i =0;i<E;i++)
	{
		int a = getRoot(road[i].a);
		int b = getRoot(road[i].b);
		if (a!=b)
		{
			v[a] = b;
			sum += road[i].w;//可以输出相应的边
		}
	}
}

 

#include<iostream>
#include<vector>
#include<string.h>
#include<algorithm>
#include<map>
#include<stack>
#include <queue>
#define MAX_Size 100
using namespace std;
//
//  BinaryTreeNode.h
//  BinaryTreeNode
//
//  Created by 吴珝君 on 2018/12/25.
//  Copyright  ©   2018年 闲着也是贤者. All rights reserved.
//
//邻接矩阵
typedef struct
{
	int no;//顶点信息
	char info;
}VertexType;
typedef struct
{
	int edges[MAX_Size][MAX_Size];//存放边的关系
	char  vex[MAX_Size];//存放顶点的值
	int n ,e;//分别为顶点数目和边的数目
}MGrap;


//建立有向图的邻接矩阵表示
void createGrap(MGrap *g)
{
	
	cout <<"请输入顶点数和边的数"<<endl;
	cin>>g->n>>g->e;
	cout<<"请输入顶点信息"<<endl;
	for (int i =0;i<g->n;i++)
	{
		cin>>g->vex[i];
	}
	//初始化矩阵
	for (int i =0;i<g->n;i++)
	{
		for (int j =0;j<g->n;j++)
		{
			g->edges[i][j] = 0;
		}
	}
	cout<<"请输入边的信息:起始边和终止边"<<endl;
	for (int i =0;i<g->e;i++)
	{
		int start, end;
		cin>>start>>end;
		g->edges[start][end] = 1;
	}
}
//最小生成树之prim算法。
/*
算法思想:
从图中某个顶点V0开始,构造生成树的算法如下。
1)将V0到其他顶点的所有边当做候选边,
2)重复以下步骤n-1次,使得其他n-1个顶点被并入到生成树当中
	A.从候选边中选择权值最小的边输出,并将于该边另一端相接的顶点vi并入生成树中
	B.考察所有剩余顶点,如果(v,vi)的权值比lowcost[vi]更小,则用更小的权值更新lowcost[vi]

*/
void prim(MGrap *g,int v ,int &sum)
{
	int lowcost[MAX_Size]={0};
	int vset[MAX_Size] ={0};
	int min = 65535;//如果这个值比6635大,说明这两点没有连接
	int index = 0;
	//选择一个顶点,作为第一个数的顶点 并计算该点到其余顶点的权值。
	for (int i =0;i<g->n;i++)
	{
		lowcost[i] = g->edges[v][i];	
	}
	vset[v]=1;//将顶点v并入树中
	for (int i =0;i<g->n-1;i++)//选择n-1个顶点并入树中
	{
	for (int j =0;j<g->n;j++)//选择最小权值的边
	{
		if (vset[j]==0&&min>lowcost[j])
		{
			min = lowcost[j];
			index =j;//选择没有被并入树并且权值最小的边的顶点
		}
		
	}
	vset[index] =1;
	sum+= min;
	//这里要做说明的是lowcost中存的是除了当前新加入节点之外,到没有并入到树中的节点的最短距离,
	//因而,我们只需要找到新并入节点到没有并入树中的其他顶点的最小权值就行了
	for (int j=0;j<g->n;j++)
	{
		if (vset[j]==0&&g->edges[index][j]<lowcost[j])
		{
			lowcost[j] = g->edges[index][j];
		}
	}
		
	}
}

//克鲁斯卡尔算法:,每次选最小的且和已经有的树不形成环的边作为生成树的边。
//算法实现
typedef struct
{

	int a,b;
	int w;
}Road;

Road road[MAX_Size];//定义边集
int v[MAX_Size];//定义并查集
int getRoot(int a)
	{
		while(a!= v[a]) 
		a= v[a];
		return a;
	}
bool compare(Road r1,Road r2)
{
	if (r1.w<r2.w)
	{
		return true;//从小到大排序
	}
}

void mysort(Road *road,int E)
{
	vector<Road> v;
	for (int i =0;i<E;i++ )
	{
		v.push_back(road[i]);
	}
	sort(v.begin(),v.end(),compare);
}

 

void  Kruskal(MGrap g,int & sum,Road *road)
{
	int N = g.n;
	int E = g.e;
	for (int i=0;i<N;i++)
	{
		v[i] =i;
	}
	mysort(road,E);//排序
	for (int i =0;i<E;i++)
	{
		int a = getRoot(road[i].a);
		int b = getRoot(road[i].b);
		if (a!=b)
		{
			v[a] = b;
			sum += road[i].w;//可以输出相应的边
		}
	}
}
int main()
{
	MGrap g;
	createGrap(&g);
	//DFSTraverse(g);
	//BFSTraverse(g);
	system("pause");
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值