数据结构之最小生成树-prim+Kruskal
采用c++来实现prim算法和Kruskal算法
#include <stdio.h> #include <iostream> #include<algorithm> using namespace std; #define MaxInt 32767 #define MVNum 100 typedef char VerTexType; typedef int ArcType;//假设边的权值类型为整型 typedef struct { VerTexType vexs[MVNum];//顶点表 ArcType arcType[MVNum][MVNum];//邻接矩阵 int vexnum, arcnum;//图的当前点数和边数 } AMGraph; //辅助数组的定义,用来记录从顶点集U到V-U的权值最小的边 typedef struct { VerTexType adjvex; //最小边在U中的那个顶点 ArcType lowcost;// 最小边上的权值 } closedge[MVNum]; //申明函数 void MiniSpanTree_Prim(AMGraph G, VerTexType u); int LocateVex(AMGraph G, char v); int MinArc(closedge closedge); void CreateUDN(AMGraph &G); void MiniSpanTree_Kruskal(AMGraph G); int main() { AMGraph G; CreateUDN(G); MiniSpanTree_Prim(G, 'a'); printf("这是Kruskal的最小生成树算法:\n"); MiniSpanTree_Kruskal(G); return 0; } void CreateUDN(AMGraph &G) { cout << "请输入当前的点数和边数:\n"; cin >> G.vexnum >> G.arcnum; cout << "依次输入点的信息:"; for (int i = 0; i < G.vexnum; i++) { cin >> G.vexs[i]; } //初始化邻接矩阵,均置为极大值MaxInt for (int i = 0; i < G.vexnum; i++) { for (int j = 0; j < G.vexnum; j++) { G.arcType[i][j] = MaxInt; } } cout << "构造邻接矩阵:\n"; char v1, v2; int w; for (int k = 0; k < G.arcnum; k++) { cout << "输入两个相邻的顶点,及其权值:\n"; cin >> v1 >> v2 >> w; int i = LocateVex(G, v1); //确定V1,V2在G中的位置 int j = LocateVex(G, v2); printf("%d %d %d\n", i, j, w); G.arcType[i][j] = w; G.arcType[j][i] = G.arcType[i][j]; } cout << "邻接矩阵为:\n"; for (int i = 0; i < G.vexnum; i++) { for (int j = 0; j < G.vexnum; j++) { printf(" %d ", G.arcType[i][j]); } printf("\n"); } } int LocateVex(AMGraph G, char v) { for (int i = 0; i < G.vexnum; i++) { if (v == G.vexs[i]) { return i; } } printf("没有找到索引\n"); return -1; } //辅助数组Edges的定义 typedef struct { VerTexType Head;//边的起始点 VerTexType Tail;//边的终点 ArcType lowcost;//边上的权值 } Edge; //辅助数组Vexset的定义 int Vexset[MVNum]; bool cmp(Edge x, Edge y); void MiniSpanTree_Kruskal(AMGraph G) { Edge edge[MVNum]; int index = 0; //对辅助数组进行排序 for (int i = 0; i < G.vexnum - 1; i++) { for (int j = i + 1; j < G.vexnum; j++) { if (G.arcType[i][j] != MaxInt) { edge[index].lowcost = G.arcType[i][j]; edge[index].Head = G.vexs[i]; edge[index].Tail = G.vexs[j]; index++; } } } sort(edge, edge + index, cmp); for(int i =0;i<index;i++){ printf("%c %c %d\n",edge[i].Head,edge[i].Tail,edge[i].lowcost); } //辅助数组,表示各顶点自成一个连通分量 for (int i = 0; i < G.vexnum; i++) { Vexset[i]=i; } //依次查看数组Edge中的边 for(int i =0;i<G.arcnum;i++){ int v1 = LocateVex(G,edge[i].Head);//为边的起始点Head的下标 int v2 = LocateVex(G,edge[i].Tail);//为边的终点Tail的下标 int vs1 = Vexset[v1];//获取edge[i]的起始点所在的连通分量vs1 int vs2 = Vexset[v2];//获取edge[i]的终点点所在的连通分量vs2 if(vs1!=vs2){//边的两个顶点分属于不同的连通分量 cout<<edge[i].Head<<" "<<edge[i].Tail<<endl;//输出此边 //合并vs1和vs2两个分量,即两个集合统一编号 for(int j =0;j<G.vexnum;j++){ if(Vexset[j]==vs2){ Vexset[j]=vs1;//集合编号为vs2的都改为vs1 } } } } } bool cmp(Edge x, Edge y) { return (x.lowcost) < (y.lowcost); } void MiniSpanTree_Prim(AMGraph G, VerTexType u) { //无向图G以邻接矩阵形式存储,从顶点u出发构造G的最小生成树T,输出T的各条边 int k = LocateVex(G, u);//k为顶点u的下标 // printf(" %d\n",k); closedge closedge; //初始化closedge[i] for (int j = 0; j < G.vexnum; j++) { if (j != k) { closedge[j].adjvex = u; closedge[j].lowcost = G.arcType[k][j]; } } cout << u << " "; closedge[k].lowcost = 0;//初始化,U={u} for (int i = 1; i < G.vexnum; i++) { //选择其余n-1个顶点,生成n-1条边 int k = MinArc(closedge); int u0 = closedge[k].adjvex; char v0 = G.vexs[k]; // printf("k: %d \n",k); // printf("u0:%d\n ",u0); printf("%c ", v0); closedge[k].lowcost = 0;//将第k个顶点并入U集 //更新closedge for (int j = 0; j < G.vexnum; j++) { if (G.arcType[k][j] < closedge[j].lowcost) { closedge[j].lowcost = G.arcType[k][j]; closedge[j].adjvex = G.vexs[k]; } } } } int MinArc(closedge closedge1) { //找出closedge中最小边上权值所对应的顶点编号 int minValue = MaxInt; int k = -1; for (int i = 0; i < sizeof(closedge1); i++) { if (minValue > closedge1[i].lowcost && closedge1[i].lowcost != 0) { minValue = closedge1[i].lowcost; k = i; } } return k; }
浙公网安备 33010602011771号