基本思想
- 每次從所有邊中選取權值最小的一條邊,將首尾節點加入集合T,剩余節點集合為G
- 從剩余節點組成的所有邊中再選擇一條權值最小的邊,將首尾節點加入集合T,剩余節點集合為G
- 重復2并且保證已選出的邊不構成回路,直到G中沒有節點。
和prim的區別
kruskal的計算是基于邊的,在邊比較少的情況下會比較快,邊比較多時,prim會更好。
例子為
最小生成樹.jpg --圖來自慕課網視頻
代碼
void MyGraph::kruskalTree() {
//1、將連接矩陣轉換為邊集合
int n,m;
vector<MyEdge> edge_vector = transformMatrixToEdge();
//用于判斷便于邊是否形成環路,下標為邊的起始點,值為邊的結束點
int parent[this->num];
for(int i = 0;i<this->num;i++){
parent[i] = 0;
}
for (int j = 0; j < edge_vector.size(); ++j) {
n = this->Find(parent,edge_vector[j].start);
m = this->Find(parent,edge_vector[j].end);
if(n!=m){
parent[n] = m;
cout<<this->node_array[edge_vector[j].start].data<<"--->"<<this->node_array[edge_vector[j].end].data<<" value: "<<edge_vector[j].value<<endl;
}
}
}
vector<MyEdge> MyGraph::transformMatrixToEdge() {
vector<MyEdge> edges;
for (int i = 0; i < this->num; ++i) {
for (int j = i+1; j < this->num; ++j) {
if(this->array[i*this->num+j]!=this->max_value) {
MyEdge edge = MyEdge(i,j,this->array[i*this->num+j]);
edges.push_back(edge);
}
}
}
for (int k = 0; k < edges.size(); ++k) {
for (int i = k+1; i < edges.size(); ++i) {
if(edges[k].value>edges[i].value){
MyEdge edge = MyEdge(edges[k].start,edges[k].end,edges[k].value);
edges[k] = edges[i];
edges[i] = edge;
}
}
}
return edges;
}
int MyGraph::Find(int *parent, int f) {
while(parent[f]>0){
f = parent[f];
}
return f;
}
運行結果
kruskal結果.png