圖的存儲及遍歷 深度遍歷和廣度遍歷 C++代碼實現


/*圖的存儲及遍歷*/  
#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:另外推薦一個讓大家真正練手的網站:豬八戒威客網,在這里可以按自己的能力去接一些程序設計的任務。我覺得這是一種很不錯的學習方法,當你接了別人的任務,無形中就給了自己壓力和動力,然后就會主動的去查詢資料,分析問題,可能會歷經艱辛才能解決問題,但這中間的過程是很珍貴的,你會通過自己的努力學到很多課本上沒有學到的東西,也能過一回需求分析的癮,真實的體會到和客戶進行交流的諸多“糾結”,最后,如果你的努力得到客戶的認可,可以獲得一筆小小的佣金,當做對自己的獎勵,更重要的是,通過做任務,你能體會到自己存在的價值感和對自己能力的肯定!

推薦:http://www.cnblogs.com/roucheng/p/cpphong.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM