數據結構無向圖的鄰接鏈表的存儲方式:頂點用一維數組儲存,每個頂點構成一個線性表,用單鏈表的形式表達
1.結構體的創建
#define MAX 20 //線性表中的結點 typedef struct ENode{ int index; //該數據的下標 struct ENode *next;//下一個結構體 }ENode; //頂點信息 typedef struct Node{ char data; struct ENode *firstNode; //指向節點的指針 }Node; //鏈接表的信息 typedef struct Graph{ int vexNum; //頂點數量 int arcNum; //邊的數量 Node vexs[MAX]; //頂點數組 用.的方式訪問 }Graph,*myGraph;
2.無向圖的鄰接鏈表的創建
void createGraph(myGraph &G) { G=(Graph*)malloc(sizeof(Graph)); //結構體的指針要初始化 int i,j,k; char v1,v2; //邊的兩個頂點 printf("請輸入頂點的數量:"); scanf("%d",&G->vexNum); printf("請輸入邊的數量:"); scanf("%d",&G->arcNum); printf("請依次將頂點數據輸入進來\n"); for(i=0;i<G->vexNum;i++) { getchar(); scanf("%c",&G->vexs[i].data); G-> vexs[i].firstNode=NULL;//頂點指向的線性表為空 } printf("請依次將邊輸入進來\n"); for(int i=0;i<G->arcNum;i++) { getchar(); scanf("%c%c",&v1,&v2); j=getLocate(G,v1); //獲取下標 k=getLocate(G,v2); //獲取下標 //v1v2邊 jk ENode *currentNode1=(ENode*)malloc(sizeof(Node));//生成臨時結點 currentNode1->index=k; //儲存的下標 currentNode1->next=NULL; //指針指向的節點為空 if(G->vexs[j].firstNode==NULL)//當該頂點沒有鄰接點時 { G->vexs[j].firstNode=currentNode1; //指向這個結點 } else //該頂點有鄰接點時 { ENode *p=G->vexs[j].firstNode; //避免 G->vexs[j].firstNode 會發生改變 while(p->next!=NULL) //指向該頂點線性表中的最后一個節點 { p=p->next; } p->next=currentNode1; //指向這個結點 } //v2v1邊 kj ENode *currentNode2=(ENode*)malloc(sizeof(Node));//生成臨時結點 currentNode2->index=j; //儲存的下標 currentNode2->next=NULL; //指針指向的節點為空 if(G->vexs[k].firstNode==NULL)//當該頂點沒有鄰接點時 { G->vexs[k].firstNode=currentNode2; //指向這個結點 } else //該頂點有鄰接點時 { ENode *q=G->vexs[k].firstNode; //避免 G->vexs[j].firstNode 會發生改變 while(q->next!=NULL) //指向該頂點線性表中的最后一個節點 { q=q->next; } q->next=currentNode2; //指向這個結點 } } }
3.鄰接鏈表的深度優先遍歷
void DFS(myGraph G,int i,int *visit) { if(!visit[i])//如果沒有訪問過 { ENode *node;//臨時結點 visit[i]=1; printf("%c ",G->vexs[i].data); //輸出該頂點信息 node=G->vexs[i].firstNode; //避免破壞 G->vexs[i].firstNode while(node!=NULL)//該鄰接點不為空 { if(!visit[node->index]) //如果該鄰接點沒有被訪問過 { DFS(G,node->index,visit); } node=node->next; } } }
4.鄰接鏈表的廣度優先遍歷
void BFS(myGraph G,int *visit) //隊列滿足先進先出的規律 { int front=0; int rear=0; int Queue[G->vexNum]; int i,j; ENode *node; for(i=0;i<G->vexNum;i++)//避免出現沒有鄰接點的頂點 { if(!visit[i]) //如果沒有訪問過 { visit[i]=1; //該頂點被訪問過 printf("%c ",G->vexs[i].data); Queue[rear++]=i; //入隊列 } while(front!=rear) { j=Queue[front++]; //出隊列 node=G->vexs[j].firstNode; while(node!=NULL) { if(!visit[node->index]) { visit[node->index]=1; printf("%c ",G->vexs[node->index].data); Queue[rear++]=node->index; //入隊列 } node=node->next; } } } }
所有的代碼如下:
#include<stdio.h> #include<stdlib.h> #define MAX 20 //線性表中的結點 typedef struct ENode{ int index; //該數據的下標 struct ENode *next;//下一個結構體 }ENode; //頂點信息 typedef struct Node{ char data; struct ENode *firstNode; //指向節點的指針 }Node; //鏈接表的信息 typedef struct Graph{ int vexNum; //頂點數量 int arcNum; //邊的數量 Node vexs[MAX]; //頂點數組 用.的方式訪問 }Graph,*myGraph; //獲取頂點的下標 int getLocate(myGraph G,char v) { int i; for(i=0;i<G->vexNum;i++) { if(v==G->vexs[i].data) { return i; } } return -1; } //創建鏈表 void createGraph(myGraph &G) { G=(Graph*)malloc(sizeof(Graph)); //結構體的指針要初始化 int i,j,k; char v1,v2; //邊的兩個頂點 printf("請輸入頂點的數量:"); scanf("%d",&G->vexNum); printf("請輸入邊的數量:"); scanf("%d",&G->arcNum); printf("請依次將頂點數據輸入進來\n"); for(i=0;i<G->vexNum;i++) { getchar(); scanf("%c",&G->vexs[i].data); G-> vexs[i].firstNode=NULL;//頂點指向的線性表為空 } printf("請依次將邊輸入進來\n"); for(int i=0;i<G->arcNum;i++) { getchar(); scanf("%c%c",&v1,&v2); j=getLocate(G,v1); //獲取下標 k=getLocate(G,v2); //獲取下標 //v1v2邊 jk ENode *currentNode1=(ENode*)malloc(sizeof(Node));//生成臨時結點 currentNode1->index=k; //儲存的下標 currentNode1->next=NULL; //指針指向的節點為空 if(G->vexs[j].firstNode==NULL)//當該頂點沒有鄰接點時 { G->vexs[j].firstNode=currentNode1; //指向這個結點 } else //該頂點有鄰接點時 { ENode *p=G->vexs[j].firstNode; //避免 G->vexs[j].firstNode 會發生改變 while(p->next!=NULL) //指向該頂點線性表中的最后一個節點 { p=p->next; } p->next=currentNode1; //指向這個結點 } //v2v1邊 kj ENode *currentNode2=(ENode*)malloc(sizeof(Node));//生成臨時結點 currentNode2->index=j; //儲存的下標 currentNode2->next=NULL; //指針指向的節點為空 if(G->vexs[k].firstNode==NULL)//當該頂點沒有鄰接點時 { G->vexs[k].firstNode=currentNode2; //指向這個結點 } else //該頂點有鄰接點時 { ENode *q=G->vexs[k].firstNode; //避免 G->vexs[j].firstNode 會發生改變 while(q->next!=NULL) //指向該頂點線性表中的最后一個節點 { q=q->next; } q->next=currentNode2; //指向這個結點 } } } //鄰接鏈表的深度優先遍歷 void DFS(myGraph G,int i,int *visit) { if(!visit[i])//如果沒有訪問過 { ENode *node;//臨時結點 visit[i]=1; printf("%c ",G->vexs[i].data); //輸出該頂點信息 node=G->vexs[i].firstNode; //避免破壞 G->vexs[i].firstNode while(node!=NULL)//該鄰接點不為空 { if(!visit[node->index]) //如果該鄰接點沒有被訪問過 { DFS(G,node->index,visit); } node=node->next; } } } //鄰接鏈表的廣度優先遍歷 void BFS(myGraph G,int *visit) //隊列滿足先進先出的規律 { int front=0; int rear=0; int Queue[G->vexNum]; int i,j; ENode *node; for(i=0;i<G->vexNum;i++)//避免出現沒有鄰接點的頂點 { if(!visit[i]) //如果沒有訪問過 { visit[i]=1; //該頂點被訪問過 printf("%c ",G->vexs[i].data); Queue[rear++]=i; //入隊列 } while(front!=rear) { j=Queue[front++]; //出隊列 node=G->vexs[j].firstNode; while(node!=NULL) { if(!visit[node->index]) { visit[node->index]=1; printf("%c ",G->vexs[node->index].data); Queue[rear++]=node->index; //入隊列 } node=node->next; } } } } //打印該鄰接表 void printfGraph(Graph G) //打印表不要用指針,這樣可能會改變圖的結構 { for(int i=0;i<G.vexNum;i++) { printf("%c ",G.vexs[i].data); while(G.vexs[i].firstNode!=NULL) { printf("%d ",G.vexs[i].firstNode->index); G.vexs[i].firstNode=G.vexs[i].firstNode->next; } printf("\n"); } } int main() { Graph *G; //申明鄰接鏈表的對象 createGraph(G); //創建鄰接鏈表 printfGraph(*G); //打印該鄰接鏈表 int visit[G->vexNum]={0}; printf("圖的鄰接鏈表的深度優先遍歷如下:\n"); for(int i=0;i<G->vexNum;i++) //避免出現沒有鄰接點的頂點 { DFS(G,i,visit); } printf("\n"); for(int i=0;i<G->vexNum;i++) { visit[i]=0; } printf("圖的鄰接鏈表的廣度優先遍歷如下:\n"); BFS(G,visit); return 0; }