/*圖的存儲及遍歷*/ #include<iostream> using namespace std; //----------------------------------- //鄰接矩陣的存儲及深度和廣度遍歷 //----------------------------------- /*鄰接矩陣的類型定義*/ #define MAX 10000000 #define MAX_VERTEX_NUM 20 typedef enum{ DG,DN,UDG,UDN }GraphKind;//有向圖,有向網,無向圖,無向網 typedef struct { char vexs[MAX_VERTEX_NUM];//用一維數組存儲頂點信息 int edges[MAX_VERTEX_NUM][MAX_VERTEX_NUM];//用二維數組充當矩陣,來存儲頂點邊的信息 int vexnum,edgenum;//頂點樹和邊數 GraphKind kind;//圖的種類 }MGraph; /*構造無向圖的鄰接矩陣*/ void CreateUDG_AM(MGraph &G,int n,int e) { G.vexnum=n; G.edgenum=e; int i,j,k; for(i=0;i<n;i++) cin>>G.vexs[i];//輸入頂點信息 for(i=0;i<n;i++) for(j=0;j<n;j++) G.edges[i][j]=0;//將矩陣初始化為0 for(k=0;k<e;k++) { cin>>i>>j;//這里只用輸入對稱的邊就行,也就是輸入下矩陣或是上矩陣 G.edges[i][j]=G.edges[j][i]=1;//輸入邊的信息 } } /****************************無向圖的深度優先遍歷************************/ int visited[MAX_VERTEX_NUM]; void DF_AM(MGraph &G,int i) { int j; cout<<G.vexs[i]<<" "; visited[i]=1; for(j=0;j<G.vexnum;j++) { if((G.edges[i][j])==1&&(visited[j])==0) DF_AM(G,j); } } void DF_Traverse_AM(MGraph &G) { int i; for(i=0;i<G.vexnum;i++) { visited[i]=0; } for(i=0;i<G.vexnum;i++) { if(!visited[i]) DF_AM(G,i); } } /*********************無向圖的廣度優先遍歷*****************************/ //循環隊列的類型定義 const int Queue_Size=100; typedef struct circlQueue { int *elem; int rear; int front; int queueSize; }circlQueue; //初始化 void initQueue_C(circlQueue &Q) { Q.elem=new int[Queue_Size]; Q.front=Q.rear=0;//首尾指針相等說明隊列為空。 Q.queueSize=Queue_Size; } //入隊列 void enterQueue_C(circlQueue &Q,int x) { if(((Q.rear+1)%Q.queueSize)==Q.front)//判斷棧滿的情況 cout<<"Queue OverFlow!"; Q.elem[Q.rear]=x; Q.rear=(Q.rear+1)%Queue_Size;//尾指針應以此種方式加1,才會實現循環隊列。 } //出隊列 char outputQueue_C(circlQueue &Q) { int e; if(Q.rear==Q.front) cout<<"Queue Empty"; e=Q.elem[Q.front]; Q.front=(Q.front+1)%Q.queueSize;;//頭指針應以此種方式加1,才會實現循環隊列。 return e; } //廣度遍歷 void BF_Traverse_AM(MGraph &G) { int i,j,v; for(i=0;i<G.vexnum;i++) visited[i]=0; circlQueue Q; initQueue_C(Q);//隊列實現了“先被訪問的頂點的鄰接點”先於“后被訪問的頂點的鄰接點”被訪問 for(i=0;i<G.vexnum;i++) { if(!visited[i]) { cout<<G.vexs[i]<<" "; visited[i]=1; enterQueue_C(Q,i); while(Q.front!=Q.rear) {//這個循環是將隊列里面的頂點取出來,然后進行下面的for循環 v=outputQueue_C(Q); for(j=0;j<G.vexnum;j++) {//這個循環是將頂點的全部鄰接點依次訪問並且入隊列 if(G.edges[v][j]&&(!visited[j])) { cout<<G.vexs[j]<<" "; visited[j]=1; enterQueue_C(Q,j); } } } } } } //----------------------------------------------- //鄰接表的存儲及深度和廣度遍歷 //----------------------------------------------- typedef struct EdgeNode {//邊表結點的定義 int adjvex;//存放鄰接點在頂點表中的位置 struct EdgeNode * nextedge;//指向下一個邊表結點 int weight; }EdgeNode; typedef struct VexNode {//頂點表結點的定義 char vex;//存放頂點信息 EdgeNode * firstedge;//指向第一個邊表結點 }VexNode; typedef struct {//頂點表的定義 VexNode vexs[MAX_VERTEX_NUM]; int vexnum,edgenum; GraphKind kind; }LGraph; /*構造有向圖的鄰接表*/ void CreateDG_AL(LGraph &G,int n,int e) { int i,j,k; G.vexnum=n; G.edgenum=e; G.kind=DG; for(i=0;i<n;i++) { cin>>G.vexs[i].vex; G.vexs[i].firstedge=NULL;//初始化為空 } for(k=0;k<e;k++) { EdgeNode *p; cin>>i>>j; p=new EdgeNode; p->adjvex=j; p->nextedge=G.vexs[i].firstedge; G.vexs[i].firstedge=p;//采用頭插法 } } /*********************有向圖的深度優先遍歷**************************/ void DF_AL(LGraph &G,int v) { int j; EdgeNode *p; cout<<G.vexs[v].vex<<" "; visited[v]=1; for(p=G.vexs[v].firstedge;p;p=p->nextedge) { j=p->adjvex; if(!visited[j]) DF_AL(G,j); } } void DF_Traverse_AL(LGraph &G) { int i; for(i=0;i<G.vexnum;i++) { visited[i]=0; } for(i=0;i<G.vexnum;i++) { if(!visited[i]) DF_AL(G,i); } } /* 何問起 hovertree.com */ /*********************有向圖的廣度優先遍歷**************************/ void BF_Traverse_AL(LGraph &G) { int i,j,v; EdgeNode *p; for(i=0;i<G.vexnum;i++) visited[i]=0; circlQueue Q; initQueue_C(Q);//隊列實現了“先被訪問的頂點的鄰接點”先於“后被訪問的頂點的鄰接點”被訪問 for(i=0;i<G.vexnum;i++) { if(!visited[i]) { cout<<G.vexs[i].vex<<" "; visited[i]=1; enterQueue_C(Q,i); while(Q.front!=Q.rear) {//這個循環是將隊列里面的頂點取出來,然后進行下面的for循環 v=outputQueue_C(Q); for(p=G.vexs[v].firstedge;p;p=p->nextedge) {//這個循環是將頂點的全部鄰接點依次訪問並且入隊列 j=p->adjvex; if(!visited[j]) { cout<<G.vexs[j].vex<<" "; visited[j]=1; enterQueue_C(Q,j); } } } } } } void main() { /*MGraph G; CreateUDG_AM(G,6,6); DF_Traverse_AM(G); cout<<endl; BF_Traverse_AM(G);*/ LGraph G; CreateDG_AL(G,5,7); DF_Traverse_AL(G); cout<<endl; BF_Traverse_AL(G); }
寫這個程序給我的感覺就是亂,思路不是很清晰,遍歷的邏輯關系還掌握的不是很熟,只是大概知道是這么回事,但是讓自己去寫的話,可能就寫不出來了!還是要加大對遍歷的熟悉程度才行啊!
PS:另外推薦一個讓大家真正練手的網站:豬八戒威客網,在這里可以按自己的能力去接一些程序設計的任務。我覺得這是一種很不錯的學習方法,當你接了別人的任務,無形中就給了自己壓力和動力,然后就會主動的去查詢資料,分析問題,可能會歷經艱辛才能解決問題,但這中間的過程是很珍貴的,你會通過自己的努力學到很多課本上沒有學到的東西,也能過一回需求分析的癮,真實的體會到和客戶進行交流的諸多“糾結”,最后,如果你的努力得到客戶的認可,可以獲得一筆小小的佣金,當做對自己的獎勵,更重要的是,通過做任務,你能體會到自己存在的價值感和對自己能力的肯定!