最小生成樹(克魯斯卡爾演算法)資料結構
思路
- 雙親表示法
用雙親表示法表示單個集合,其中雙親作為標記,在同一個連通分量裡的點雙親相同(需要在開始就將雙親設定,後面會與權值比較,所以越大越好,但開始都不相同) - 三元組
三元組表示要輸入的形式 - 迭代找最小權值
在找到權值並使用後,將其變成負數,最後輸出時要變回來
問題描述:
見習題集P152。用克魯斯卡爾(Kruskal)演算法求無向網的最小生成樹。
輸入:
輸入資料第一行為兩個正整數n(1<n<=30)和m(1<m<100),分別表示頂點數和邊數。後面緊跟m行資料,每行資料是一條邊的資訊,包括三個數字,分別表示該邊的兩個頂點和邊上的權值。
輸出:
按順序輸出Kruskal演算法求得的最小生成樹的邊集,每行一條邊,包括三個數字,分別是該邊的兩個頂點和邊上的權值,其中第一個頂點的編號應小於第二個頂點的編號。
示例輸入
8 11
1 2 3
1 4 5
1 6 18
2 4 7
2 5 6
3 5 10
3 8 20
4 6 15
4 7 11
5 7 8
5 8 12
示例輸出
1 2 3
1 4 5
2 5 6
5 7 8
3 5 10
5 8 12
4 6 15
#include<stdio.h>
# define max_tree_size 100
typedef struct NODE{//邊的定義
int parent;//雙親的位置 (如果雙親相同,就在同一個集合裡)
//int next;//相關聯的節點位置
int date;//自己點的位置
}D[100];
typedef struct tri{//三元組
int x;//前繼
int y;//後繼
int weigh;//權值
}T[100];
typedef struct TREE{
tri T[100];//邊的集合
}Tree;
int findmin(tri T[],int m,NODE D[]){//找最小的邊
int min=999;
int temp;
for(int j=0;j<m;j++){//在滿足條件的情況下,直接找最小
if(T[j].weigh<=min&&T[j].weigh>0) {
min=T[j].weigh;
temp=j;
}
}
if(D[T[temp].x ].parent ==D[T[temp].y ].parent ) {
T[temp].weigh =999999;
findmin(T,m,D);
}//相等說明已經在一個集合了,該路徑不能走,直接999999,再也走不通
else {
if(D[T[temp].x ].parent<D[T[temp].y ].parent){//因為權值總是從小到大被發現,可作為雙親 ,
//前提是最開始的雙親都大於最小的權值
if(D[T[temp].x ].parent>T[temp].weigh){// 找出x,y的雙親最小的那個與當前所找到的權值比較,取較小的
D[T[temp].x ].parent=T[temp].weigh;//這樣能保證在同一個連通分量總能有相同的雙親
D[T[temp].y ].parent=T[temp].weigh;//在不同的連通分量有不同的雙親
}
else D[T[temp].y ].parent=D[T[temp].x ].parent;
}
else{
if(D[T[temp].y ].parent>T[temp].weigh){
D[T[temp].x ].parent=T[temp].weigh;
D[T[temp].y ].parent=T[temp].weigh;
}
else D[T[temp].x ].parent=D[T[temp].y ].parent;
}
T[temp].weigh=T[temp].weigh*(-1);//為了防止下一次還找到該路徑,將權值改為負數,輸出時需要改回來
return temp;
}//成功找到,將雙親設為一樣 ,在一個集合的點的雙親需要一起變
}
int main(){
int n,m;
scanf("%d %d",&n,&m);
tri T[100];
NODE D[100];
Tree p;
int i,j,k,count=0;
for(i=999;i<n;i++) D[i].parent =i;//設定一下雙親,每都不一樣 ,放到一個集合(連通分量)時就讓他們一樣
for(i=0;i<m;i++) scanf("%d %d %d",&T[i].x ,&T[i].y ,&T[i].weigh );//輸入三元組
for(i=0;i<n-1;i++){//迴圈頂點數-1次即可,就會連通
k=findmin(T,m,D);
p.T[count]=T[k];//將找到的路徑存入樹中,覺得這裡有點滑稽,感覺自己騙自己,直接輸出就完了
count++;
printf("%d %d %d\n",p.T[i].x ,p.T[i].y,p.T[i].weigh*(-1) );
}
}
感想
樣例只過了一個,因為oj時間截止了,各位如果發現什麼錯誤,歡迎指正。
感覺自己程式碼還是很複雜,向大家請教更簡單的思路
菜雞一個的我,希望大家找我交流
期末了,要瘋狂肝資料結構的題了。
相關文章
- 資料結構與演算法——克魯斯卡爾(Kruskal)演算法資料結構演算法
- 最小生成樹---普里姆演算法(Prim演算法)和克魯斯卡爾演算法(Kruskal演算法)演算法
- ACM日常訓練日記——8.8(二分dp,最小生成樹+克魯斯卡爾演算法和普利姆演算法)ACM演算法
- 資料結構與演算法之最好學的最小生成樹資料結構演算法
- 演算法與資料結構之帶權圖與圖最小生成樹演算法資料結構
- 資料結構------最短路徑Dijkstra和最小生成樹Prim資料結構
- 資料結構和演算法學習筆記八:帶權連通圖的最小生成樹資料結構演算法筆記
- 最小生成樹__Kurskal演算法演算法
- 最小生成樹__Prim演算法演算法
- 最小生成樹的演算法演算法
- Kruskal 最小生成樹演算法演算法
- 最小生成樹之 Prim 演算法演算法
- 【演算法學習】最小生成樹演算法
- 演算法-圖論-最小生成樹演算法圖論
- 資料結構與演算法:AVL樹資料結構演算法
- [演算法] 資料結構之AVL樹演算法資料結構
- 最小生成樹
- 克魯斯焊機GL 270引弧困難維修
- 最小樹形圖(有向圖的最小生成樹)朱劉演算法演算法
- 最小生成樹——Prim演算法和Kruscal演算法演算法
- 最小生成樹:Kruskal演算法和Prim演算法演算法
- 最小生成樹-Prim演算法和Kruskal演算法演算法
- [演算法] 資料結構 splay(伸展樹)解析演算法資料結構
- 資料結構——樹資料結構
- 資料結構-樹資料結構
- 最小生成樹prim普里姆演算法演算法
- 最小生成樹之普里姆演算法演算法
- Boruvka求最小生成樹(菠蘿演算法)演算法
- 圖論中的最小生成樹演算法圖論演算法
- 軟體開發定律系列之布魯克斯定律有感
- 最小度限制生成樹
- 【模板】最小生成樹
- 演算法學習之路|最小生成樹——prime演算法演算法
- 最小生成樹之Prim演算法和Kruskal演算法演算法
- 【資料結構與演算法】二叉樹資料結構演算法二叉樹
- 05 Javascript資料結構與演算法 之 樹JavaScript資料結構演算法
- 資料結構與演算法:哈夫曼樹資料結構演算法
- 資料結構和演算法:二叉樹資料結構演算法二叉樹