資料結構——圖的儲存與遍歷(鄰接矩陣)
阿新 • • 發佈:2018-11-29
圖的儲存與遍歷(鄰接矩陣)
#include<stdio.h> #include<stdlib.h> #define MAXVEX 20 /*最大頂點個數*/ #define INFINITY 32767 /*表示無窮,可自定義*/ #define Elem int #define FALSE 0 #define OK 1 #define TRUE 1 typedef char VertexType; typedef struct{ int arcs[MAXVEX][MAXVEX]; //鄰接矩陣,邊的資訊 VertexType vexs[MAXVEX]; //頂點資訊 int vexnum; //頂點數目 int arcnum; //邊(弧)數目 }AdjMatrix; //根據名稱得到指定頂點在頂點集合中的下標 int getIndexOfVexs(char vex,AdjMatrix *MG) { for(int i=1;i<=MG->vexnum;i++) { if(MG->vexs[i]==vex) return i; } return 0; } //用鄰接矩陣建立圖 void Create(AdjMatrix *MG){ int v1,v2; char c1,c2; printf("請輸入頂點數目: "); //輸入頂點數 scanf("%d",&MG->vexnum); printf("請輸入邊的數目: "); //輸入邊數 scanf("%d",&MG->arcnum); getchar(); //輸入各頂點資訊 for(int i=1;i<=MG->vexnum;i++) { printf("請輸入第%d個頂點(char): ",i); //請輸入各頂點資訊 scanf("%c",&MG->vexs[i]); getchar(); } //初始化鄰接矩陣 for(int i=1;i<=MG->vexnum;i++) for (int j=1;j<=MG->vexnum;j++) MG->arcs[i][j]=0; /*如果是網則賦值INFINITY */ //輸入邊的資訊,建立鄰接矩陣 for(int k=1;k<=MG->arcnum;k++) { printf("請輸入第%d個邊連線的兩個頂點v1(char) v2(char): ",k); //請輸入有關係的兩個頂點 scanf("%c %c",&c1,&c2); v1=getIndexOfVexs(c1,MG); v2=getIndexOfVexs(c2,MG); MG->arcs[v1][v2]=1; MG->arcs[v2][v1]=1; //無向圖為對稱矩陣 getchar(); } } //列印圖的資訊 void Printf(AdjMatrix MG) { printf("頂點數目為: %d\n",MG.vexnum); printf("邊的數目為: %d\n",MG.arcnum); printf("頂點: "); for(int i=1;i<=MG.vexnum;i++) printf("%c",MG.vexs[i]); printf("\n鄰接矩陣為: \n"); for(int i=1;i<=MG.vexnum;i++) { for(int j=1;j<=MG.vexnum;j++) printf("%d",MG.arcs[i][j]); printf("\n"); } } /******************遞迴深度優先遍歷函式***********************/ void visit(AdjMatrix G,int v){ printf("%c",G.vexs[v]); } int FirstAdjVex(AdjMatrix G,int v){ //尋找圖G中v的第一個鄰接點 for(int i=1;i<G.vexnum;i++){ if(G.arcs[v][i]!=0) return i; } return -1; } int NextAdjVex(AdjMatrix G,int v,int w){ //尋找圖G中v頂點在w之後的下一個鄰接點 for(int i=w+1;i<G.vexnum;i++){ if(G.arcs[v][i]!=0) return i; } return -1; } int visited[MAXVEX]={0}; //訪問標誌陣列 void DFS(AdjMatrix G,int v){ //遞迴深度優先遍歷連通子圖 visit(G,v); //檢視v; visited[v]=1; int w=FirstAdjVex(G,v); //圖G中v的第一個鄰接點 while(w!=-1){ //如果沒有鄰接點則返回-1 if(!visited[w]) DFS(G,w); //如果w沒有被訪問過,則對w進行深度優先遍歷 w=NextAdjVex(G,v,w); //尋找圖G中v的下一個鄰接點 } } void TraverseG(AdjMatrix G){ //深度優先遍歷圖 for(int v=1;v<=G.vexnum;v++) //標誌陣列初始化 visited[v]=0; printf("\n深度優先遍歷:"); for(int v=1;v<=G.vexnum;v++){ if(!visited[v]) DFS(G,v); } } /*******************廣度優先遍歷函式(相似與二叉樹的層次遍歷)***********************/ /********佇列函式*******/ typedef struct array{ //定義佇列結構 Elem elem; struct array *next; }*PLArray; typedef struct Node_D{ PLArray front; //指向隊頭 PLArray rear; //指向隊尾 int len; //佇列實際長度 }*pNode; void InitArray(pNode &S){ //構造空佇列 PLArray q=(PLArray)malloc(sizeof(PLArray)); //申請新結點 S=(pNode)malloc(sizeof(pNode)); S->front=q; S->rear=q; S->front->next=NULL; S->len=0; } int Push(pNode &S,Elem e){ //插入資料e為佇列的隊尾 PLArray p=(PLArray)malloc(sizeof(PLArray)); //申請新結點 p->elem=e; p->next=NULL; S->rear->next=p; //將結點插入到隊尾 S->rear=p; //修改隊尾指標 S->len++; } int Pop(pNode &S,Elem &e){ //刪除隊頭元素,,用e返回其刪除資料 if(S->front==S->rear) return FALSE; PLArray p=S->front->next; //p指向隊頭 e=p->elem; S->front->next=p->next; //修改頭結點的指標域 if(S->rear==p) S->rear=S->front; //最後元素被刪除 S->len--; return OK ; } int ArrayEmpty(pNode &S){ //判斷佇列是否為空 if(S->len==0) return TRUE; else return FALSE; } int Refer(pNode &S,Elem &e) { //查詢隊頭元素 e=S->front->next->elem; } /*廣度優先遍歷的 visit函式,FirstAdjVex函式,NextAdjVex函式 功能相同不重複定義 */ int visited2[MAXVEX]={0}; //訪問標誌陣列 void BFS(AdjMatrix G,int v){ //廣度優先遍歷連通子圖 visit(G,v); visited2[v]=1; pNode Q; InitArray(Q); //建立空佇列 Push(Q,v); //入隊 while(!ArrayEmpty(Q)){ //當佇列非空時 Pop(Q,v); //出隊 int w=FirstAdjVex(G,v); //圖G中v的第一個鄰接點 while(w!=-1){ //遍歷v的所有鄰接點 if(!visited2[w]){ visit(G,w); visited[w]=1; Push(Q,w); } w=NextAdjVex(G,v,w); //尋找圖G中v的下一個鄰接點 } } } void TraverseG_2(AdjMatrix G){ //廣度優先遍歷圖 for(int v=1;v<=G.vexnum;v++) //標誌陣列初始化 visited2[v]=0; printf("\n廣度優先遍歷:"); for(int v=1;v<=G.vexnum;v++){ if(!visited2[v]) DFS(G,v); } } int main(){ AdjMatrix MG; Create(&MG); Printf(MG); TraverseG(MG); TraverseG_2(MG); return 0; }