最小生成树(Kruskal算法)
算法简介:
Kruskal算法是一种用来查找最小生成树的算法,由Joseph Kruskal在1956年发表。用来解决同样问题的还有Prim算法和Boruvka算法等。三种算法都是贪心算法的应用。和Boruvka算法不同的地方是,Kruskal算法在图中存在相同权值的边时也有效。
算法讲解:
将所有的边按照从小到大进行排序。然后依此从最小边开始检测,如果当前边的两个节点拥有相同的根节点,则构成回路。如果没有相同的根节点则证明不会造成回路,将当前两个节点合并成一棵树。(确定是否造成回路会用到并查集的概念,并查集的作用就是获得当前节点的根节点。)直至所有的边全部检测完毕就完成了我们的寻找最小生成树的任务,这就是克鲁斯卡尔算法。
代码实现:
//首先定义边的类
class Road{
int a, b; //连接一条边的两个节点
int w; //该条边的权值
}
//边的列表,假设列表中已经存有数据
List<Road> roadList = new ArrayList<Road>();
int v[maxsize]; //并查集数组
//查找根节点的方法
int getRoot(int a){
while(a != v[a]) a = v[a];
return a;
}
void Kruskal(Graph g, List<Road> roadList){
int N, G, a, b;
N = g.n;
E = g.edge;
for(int i=0; i<N, i++){
//令节点的根节点等于其本身
v[i] = i;
}
//对list的排序方法省略
Sort(roadList);
for(int i=0; i<E; i++){
a = getRoot(roadList.get(i).a);
b = getRoot(roadList.get(i).b);
if(a != b){
v[a] = b;
}
}
}
时间复杂度:
该算法的时间主要花费在边的排序和单层循环上,排序算法是线性级的,因此任务主要的时间都花费在边权值的排序上。 该算法的时间复杂度由排序算法而定,排序所要处理的数据量由于边的数量有关。因此,影响该算法效率的因素是边的数量。该算法适用于边数较少的稀疏图。