目录
前言
一直说要开始写CSDN可是不知道从哪里开始,今天不知道怎么突然很想写,就写了一下最小生成树。(本来最短路径也想要写的可是有点写不完了好像 就放到下次吧!)Kruscal算法在上次作业里好像只写了个排序,趁着写CSDN好好复习一下啦。要期末了如果有空的话我会继续写就当作复习啦。顺便说我好喜欢在这里的碎碎念 好像我和知识更熟了一点()
一、生成树
好像老师没有很提到生成树的概念,可能是觉得不很重要?
但是我这么爱问为什么的人怎么能不知道呢,嘻嘻()
生成树
- 定义:①所有顶点都由边相连②无回路
- 特点:
- n个顶点,n-1条边
- 是极小连通子图:少一条边就非连通,多一条边就回路
- 生成树中任意两顶点之间路径唯一
- 一个图可以有多颗不同的生成树
最小生成树
各边权值最小的生成树
MST性质
这个似乎很重要 但我也没有很懂其实 贴张图在这里吧
二、Prime算法
1.原理
一张图包含了所有我想说的(绿色是下一步)
2.代码
//定义结构体
typedef struct{
int adjvex; //最小边的前一个结点(from)
int lowcost; //最小边的权值
}shortEdgeNode;
//找到已知的 不在U里的 最小边
int MinEdge(shortEdgeNode shortEdge[],int n){
int min=INF;
int k=-1; //返回-1就是没有 全都是
for(int i=0;i<n;i++){
if(shortEdge[i].lowcost!=0 && shortEdge[i].lowcost<min){
min=shortEdge[i].lowcost;
k=i;
}
}
return k;
}
//Prime(返回最小代价)
int FindMinWeight_Prime(const Graph &g,int start){
int ans=0;
shortEdgeNode shortEdge[g.vexNumber]; //储存的是每个点到U的最小权值!!!
for(int i=0;i<g.vexNumber;i++){
shortEdge[i].adjvex=start; //初始化是start直达的权值
shortEdge[i].lowcost=g.adjMatrix[start][i];
}
shortEdge[start].lowcost=0; //自己到自己是0
for(int i=0;i<g.vexNumber-1;i++){
int k=MinEdge(shortEdge,g.vexNumber); //这里用到函数MinEdge
ans+=shortEdge[k].lowcost;
shortEdge[k].lowcost=0; //找到最小的就纳入U 这样自己到自己为0
for(int j=0;j<g.vexNumber;j++){
if(g.adjMatrix[k][j]<shortEdge[j].lowcost){
shortEdge[j].lowcost=g.adjMatrix[k][j]; //如果新加入节点到j距离更小 更新lowcost值
shortEdge[j].adjvex=k;
}
}
}
return ans;
}
三、Kruskal算法
1.原理
从边最小的开始 只要不成环 就加进去
重点是判断是否成环。这里是把每一个结点看成独立的树,每加入一条边,就是在对两棵树合并。所以需要在加入边之前判断这个边连接的两个顶点是否在同一棵树,通过parent数组一直向上查找直到找到根节点就可以啦。
2.代码
//边节点
typedef struct{
int from,to;
int weight;
}EdgeType;
//边从小到大排序
void sort_Kruscal(EdgeGraph &eg){
for(int i=0;i<eg.edgeNum;i++){
for(int j=i+1;j<eg.edgeNum;j++){
if(eg.edge[i].weight>eg.edge[j].weight){
EdgeType t;
t=eg.edge[i];
eg.edge[i]=eg.edge[j];
eg.edge[j]=t;
}
}
}
}
int parent[MAX_SIZE];
//寻找生成树的根节点
int findRoot(int v){
int t=v;
while(parent[t]!=-1){ //-1表示是根节点
t=parent[t];
}
return t; //!注意这里返回的是具体某个节点
}
//Kruscal(返回最小代价)
int Kruscal(EdgeGraph &eg){
memset(parent,-1,sizeof parent); //初始化parent数组 最开始各个顶点独立 都是根节点
sort_Kruscal(eg);
int ans=0;
int num=0;
for(int i=0;i<eg.edgeNum;i++){
int vex1=findRoot(eg.edge[i].from);
int vex2=findRoot(eg.edge[i].to);
if(vex1!=vex2){ //如果根节点不同说明不能成环
parent[vex2]=vex1; //合并两树
ans+=eg.edge[i].weight;
num++;
if(num==eg.vertexNum-1){ //结束条件是 生成树的边数=n-1
return ans;
}
}
}
return -1; //如果遍历完成num<eg.vertexNum-1 说明不能生成
}
总结
我的第一篇CSDN耶耶耶!