prim算法
有两个集合,第一个集合,存放最小生成树,第二个集合,用来存放还没有进入最小生成树的结点。但这两个集合实际上是用同一个数组表示的。
我们用closedge[100]来表示这个数组,每个单元由“string Data;”和“int lowcost;”两部分组成。其中closedge[1]表示图中的第一个结点v1,closedge【1】.Data表示v1到最小生成树最短路径的结点(假设为v2),closedge【1】.lowcost就是v1到v2的距离。如果closedge【1】.lowcoat为0,就说明它已经在最小生成树中了。
prim算法的核心思想,就是以最小生成树为研究对象,每次在还没有进入最小生成树的结点中,找到路径最小的那个。
- 假设目前的最小生成树为v2,v1是所有结点中,到它最短的一个,那么我们就把v1加入到最小生成树中;
- 过程为:closedge【1】.lowcoat赋为0;把closedge【1】.Data赋为v1;
- 在剩下的结点中,寻找是否有结点到v1的距离,小于此几点到v2的距离,如果有,那么此时此节点到最小生成树的距离,就是到v1的距离。总共n个结点,就重复此步骤n-1次。
struct Node
{
string Data;
int lowcost;
}closedge[100];
int Get_Location(Graph T,string name)
{
for(int i = 1; i <= T.Vex_num; i++)
{
if(T.Name[i] == name)
return i;
}
cout<<"Error!Not found!"<<endl;
exit(1);
}
int Get_Min(Node closedge[],int n)
{
int Min = 100;int index;
for(int i = 1; i <= n; i++)
{
if(closedge[i].lowcost < Min && closedge[i].lowcost != 0)
{
Min = closedge[i].lowcost;
index = i;
}
}
return index;
}
void MiniSpanTree_prim(Graph T,string name)
{
int k = Get_Location(T,name); //确认开始点位置
closedge[k].lowcost = 0; //开始点此时就是最小生成树
for(int i = 1; i <= T.Vex_num; i++)
{
if(i != k) //剩下的所有结点到最小生成树的距离
closedge[i] = {name,T.Arr[k][i]};
}
string n1, n2;
cout<<"最小生成树"<<endl<<"从\t"<<"到"<<endl;
for(int i = 1; i < T.Vex_num; i++)
{
k = Get_Min(closedge,T.Vex_num); //到最小生成树距离的最小结点位置
n1 = closedge[k].Data; //与次结点相连的最小成成树中的结点
n2 = T.Name[k]; //此结点
cout<<n1<<"\t"<<n2<<endl;
closedge[k].lowcost = 0; //此节点进入最小生成树
for(int j = 1; j <= T.Vex_num; j++)
{
if(T.Arr[j][k] < closedge[j].lowcost)
closedge[j] = {T.Name[k],T.Arr[j][k]};
}
}
}
//测试数据
/*
6 10
v1 v2 v3 v4 v5 v6
v1 v2 6
v1 v4 5
v1 v3 1
v2 v3 5
v2 v5 3
v3 v4 5
v3 v5 6
v3 v6 4
v4 v6 2
v5 v6 6
*/
Kruskal算法
- 把所有的边都放到一个叫Edge的辅助数组中,并从小到大排序;
- 再设一个存放每个结点所在连通分量的辅助数组,初始每个结点都在自己的连通分量中:Vexset[v1]=1,Vexset[2]=2,Vexset[i]=i;
- 每次找到权重最小的边,如果此边的两个结点,没有在同一个连通分量中,就把这条边加入最小生成树;
#include<iostream>
#include<algorithm>
using namespace std;
struct Graph
{
int Arr[100][100];
string Name[100];
int Vex_num, Edge_num;
};
struct Node
{
string head;
string tail;
int weight;
}Edge[100];
int Vexset[100];
int Get_Location(Graph T,string name)
{
for(int i = 1; i <= T.Vex_num; i++)
{
if(T.Name[i] == name)
return i;
}
}
void Create_Graph(Graph & T)
{
cin>>T.Vex_num>>T.Edge_num;
for(int i = 1; i <= T.Vex_num; i++)
{
cin>>T.Name[i];
}
int x, y, w; string n1, n2;
for(int i = 1; i <= T.Edge_num; i++)
{
cin>>n1>>n2>>w;
Edge[i].head = n1;Edge[i].tail = n2;
Edge[i].weight = w;
x = Get_Location(T,n1);
y = Get_Location(T,n2);
T.Arr[x][y] = w;T.Arr[y][x] = w;
}
}
int comp(Node n1, Node n2)
{
return n1.weight < n2.weight;
}
void MiniSpanTree_Kruskal(Graph T)
{
sort(Edge,Edge + T.Edge_num + 1,comp);
for(int i = 1; i <= T.Vex_num; i++)
Vexset[i] = i;
int x, y; int n1, n2;
for(int i = 1; i <= T.Edge_num; i++)
{
x = Get_Location(T,Edge[i].head);
y = Get_Location(T,Edge[i].tail);
n1 = Vexset[x];n2 = Vexset[y];
if(n1 != n2)
{
cout<<Edge[i].head<<"\t"<<Edge[i].tail<<endl;
for(int j = 1; j <= T.Vex_num; j++)
{
if(Vexset[j] == n2)
Vexset[j] = n1;
}
}
}
}
int main()
{
Graph T;
Create_Graph(T);
MiniSpanTree_Kruskal(T);
}
/*
6 10
v1 v2 v3 v4 v5 v6
v1 v2 6
v1 v4 5
v1 v3 1
v2 v3 5
v2 v5 3
v3 v4 5
v3 v5 6
v3 v6 4
v4 v6 2
v5 v6 6
*/