標籤:algorithm c 演算法 連通
最近在看《Algorithms IN C》這本書,剛開始看,讀的是英文版的,感覺作者的敘述有點不太容易理解,就找了一本中文版的來看,發現還是看英文版的比較好。先看了第一章的大部分,後面的總結還沒有看,我的感受是,一個小的問題只需要找到一個正確的演算法就可以了,根本不許要去考慮演算法的效率和效能,只有在解決一些大型的實際問題時,演算法的優劣才能體現出來。另外,就是增加機器的效能遠不如改善演算法的效能貢獻大。
第一章舉了一個連通性的例子,作者一步一步的引導我們來改進演算法,使得這個演算法最終可以真正的用在實際問題中。這個問題的描述及四個解決演算法,如下:
問題描述 輸入兩個整數,代表兩個節點,如果這兩個整數沒有建立串連(這包括直接連接和通過其他節點串連),那麼我們就建立這兩個節點之間的串連,否則,繼續輸入下一個節點
四個逐步改進的演算法如下:
//演算法一#include <stdio.h>#define N 10int main(void){ int id[N]; int t,i,p,q; //一定要初始化啊 for(i=0;i<N;i++) { id[i] = i; } while( scanf("%d%d",&p,&q)==2 ) { if( id[p]==id[q] ) continue; t = id[p]; for(i=0;i<N;i++) { if( id[i]==t ) { id[i] = id[q]; } } for(i=0;i<N;i++) { printf("%d\t",id[i]); } printf("\n"); } return 0;}
這四個演算法所使用的資料結構都是數組,演算法一是把串連(包括直接連接和間接串連)在一起的整數所對應的數組元素都賦值為相同的值。
//演算法二#include <stdio.h>#define N 10int main(void){ int id[N]; int i,j,p,q; for(i=0;i<N;i++) { id[i] = i; } while( scanf("%d%d",&p,&q)==2 ) { //必須使用下面兩次迴圈,否則當心陷入死迴圈 for(i=p;id[i]!=i;i=id[i]); for(j=q;id[j]!=j;j=id[j]); if( i==j ) continue; id[i] = j; for(i=0;i<N;i++) { printf("%d\t",id[i]); } printf("\n"); } return 0;}
演算法二採用的資料結構仍然是數組,但是邏輯上確實樹的結構。我們首先根據輸入的兩個整數,分別找到其所在的樹的根節點,然後檢測兩個節點所在的樹的根節點是否相同,如果相同,就說明是同一棵樹,否則就把這兩個根節點串連起來。
//演算法三#include <stdio.h>#define N 10int main(void){int id[N],sz[N];int p,q,i,j;for(i=0;i<N;i++){id[i] = i;sz[i] = 1;}while( scanf("%d%d",&p,&q)==2 ){for(i=p;id[i]!=i;i=id[i]);for(j=q;id[j]!=j;j=id[j]);if( sz[i]<sz[j] ){id[i] = j;sz[j] += sz[i];}else{id[j] = i;sz[i] += sz[j];}printf("i=%d\nj=%d\n",i,j);for(i=0;i<N;i++){printf("%d\t",sz[i]);}printf("\n");for(i=0;i<N;i++){printf("%d\t",id[i]);}printf("\n");}return 0;}
演算法三是在演算法二的基礎之上改進而來的,但是它添加了一個資料結構,記錄以每個節點為根的樹中的元素的個數。通過這個資料結構,每次都把小樹串連到大樹上,防止樹的深度過深。
//演算法四#include <stdio.h>#define N 10int main(void){int id[N];int sz[N];int p,q,i,j;//初始化for(i=0;i<N;i++){id[i] = i;sz[i] = 1;}while( scanf("%d%d",&p,&q)==2 ){for(i=p;id[i]!=i;i=id[i]){id[i] = id[id[i]];}for(j=q;id[j]!=j;j=id[j]){id[j] = id[id[j]];}if( sz[i]<sz[j] ){id[i] = j;sz[j] += sz[i];} else{id[j] = i;sz[i] += sz[j];} printf("i=%d\nj=%d\n",i,j); for(i=0;i<N;i++) { printf("%d\t",sz[i]); } printf("\n"); for(i=0;i<N;i++) { printf("%d\t",id[i]); } printf("\n");}return 0;}
演算法四就是在演算法三的基礎之上又做了進一步的改進,將樹的深度進一步的縮小。
關於第二章演算法分析的部分,準備留到以後再看,現在看了沒什麼深得體會,下一部分,準備開始看資料結構。