1 圖的定義數組
多對多的數據結構,由頂點的非空集合和頂點之間的邊的集合組成;數據結構
1.1 圖的概念spa
數據元素3d
在線性表中稱爲元素;在樹中稱爲結點、在圖中稱爲頂點指針
數據元素集合code
在線性表中能夠沒有元素稱爲空表;在樹中能夠沒有結點稱爲空樹;在圖中不能沒有頂點,即頂點集合不能爲空blog
數據元素之間的關係get
在線性表中稱爲線性關係;在樹中稱爲層次關係;在圖中稱爲邊的關係,邊的集合能夠爲空;it
1.2 圖的種類io
1.3 圖的概念
2 圖的抽象數據類型
ADT圖
data:頂點的非空又窮集合和邊的有限集合
operation creatGraph(G,V,VR) //按照頂點集合V和邊的集合VR構建圖G destroyGraph(G) //銷燬圖G locateGraph(G,V)//若圖G中存在頂點V,則返回V在圖中的位置 getVex(G,V)//返回圖G中,頂點V的值 putVex(G,V,x)//將圖G中頂點V賦值爲x firstAdjVex(G,V)//獲取圖G中頂點V的一個鄰接頂點 nextAdjVex(G,V,W)//獲取圖G中頂點V相對於頂點W的下一個鄰接頂點 insertVex(G,V)//在圖G中添加一個頂點V deleteVex(G,V)//刪除圖G中的頂點V,及相關的邊 insertArc(G,V,W)//在圖G中添加弧<V,W> deleteArc(G,V,W)//在圖G中刪除弧<V,W> DFSTraverse(G)//圖G的先深搜索 HFSTraverse(G)//圖G的先廣搜索 endADT
3 圖的存儲結構
3.1 鄰接矩陣
由兩個數組表示圖;一個是存儲頂點的數組,一維數組;一個是存儲邊或弧的數組,二維數組;
3.2 鄰接表
由數組和鏈表表示圖;一個是存儲頂點的數組,每一個數組元素由頂點、第一條邊指針組成;還有一個存儲邊或弧的鏈表;
結點結構
3.3 十字鏈表
由一維數組和鏈表表示圖;一個是存儲頂點的一維數組,每一個數組元素由頂點、入邊結點指針、出邊結點指針組成;還有一個存儲邊或弧的十字鏈表;
3.4 鄰接多重表
由數組和鏈表表示圖;一個存儲頂點的數組;還有一個是存儲邊的十字鏈表
3.5 邊集數組
由二個一維數組表示圖;一個是存儲頂點的數組;另外一個是存儲邊或弧的數組,每一個數組元素由弧頭、弧尾、權組成;
4 圖的遍歷
從圖中某一頂點出發,使圖中其他頂點都被訪問到,且僅被訪問一次的方法
具體方法是經過定義一個數組visited[n],其中:
n:表示圖中頂點的個數
visited[i]的值,(n>i>=0)
值爲0表示該頂點未被訪問過;
值爲1表示該頂點已被訪問過;
圖的遍歷方法
深度優先搜索
廣度優先搜索
4.1 深度優先搜索
4.1.1 鄰接矩陣
typedef int VType; //頂點的數據類型 typedef int EType; //邊的數據類型 #define VSIZE 100; //最大頂點數 typedef struct AdjMGraph { VType vex[VSIZE]; //頂點數組 EType arc[VSIZE][VSIZE]; //邊弧數組 int VNum; int ENum; }AdjMGraph; /* 建立鄰接矩陣 */ void creatAdjMGraph(AdjMGraph *g) { printf("輸入頂點個數:"); scanf("%d",&g->VNum); printf("輸入頂點間的邊數:"); scanf("%d",&g->ENum); for(int i=0;i<g->VNum;i++) scanf("%d",&g->vexs[i]); for(int i=0;i<g->VNum;i++) for(int j=0;j<g->VNum;j++) g->arc[i][j]=0; for(int k=0;k<g->ENum;k++) { printf("輸入邊(vi,vj)的下標i,j"); int i,j; scanf("%d %d",&i,&j); g->arc[i][j]=g->arc[j][i]=1; } } int visited[VSIZE]; void (*visitFunc)(VType t); void print(VType t) { printf("%d\n",t); } void DFS(AdjMGraph g,int i) { visited[i]=1; visitFunc(g.vexs[i]); for(int j=0;j<g.VNum;j++) { if(g.arc[i][j]==1 && visited[j]==0) { DFS(g,j); } } } void DFSTraverse(AdjMGraph g,void (*vf)(VType t)) { visitFunc=vf; for(int i=0;i<g.VNum;i++) { visited[i]=0; } for(int i=0;i<g.VNum;i++) { if(visited[j]==0) { DFS(g,j); } } } void main() { AdjMGraph g; //定義鄰接矩陣圖 creatAdjMGraph(&g); //建立鄰接矩陣圖 DFSTraverse(g,print); //遍歷鄰接矩陣圖 }
4.1.2 鄰接表
typedef int VType; //頂點的數據類型 typedef int EType; //邊的數據類型 #define VSIZE 100; //最大頂點數 typedef struct ENode //邊鏈表結點 { int v; //頂點下標 struct ENode *next; //下一個頂點的指針 }ENode; typedef struct VNode //頂點表結點 { VType data; //頂點中的數據 struct VNode *first; //第一個邊鏈表結點的指針 }VNode; typedef struct AdjMGraph { VType vex[VSIZE]; //頂點數組 int VNum; //頂點數 int ENum; //邊數 }AdjMGraph; /* 建立鄰接表 */ void creatAdjMGraph(AdjMGraph *g) { printf("輸入頂點個數:"); scanf("%d",&g->VNum); printf("輸入頂點間的邊數:"); scanf("%d",&g->ENum); for(int i=0;i<g->VNum;i++) { printf("輸入頂點%d的數據:",i); scanf("%d",&g->vexs[i].data); g->vexs[i].first=NULL; } for(int k=0;k<g->ENum;k++) { printf("輸入邊(vi,vj)的下標i,j"); int i,j; scanf("%d %d",&i,&j); ENode *p=(ENode*)malloc(sizeof(ENode)); p->v=j; p->next=g->vexs[i].first; g->vexs[i].first=p; p=(ENode*)malloc(sizeof(ENode)); p->v=i; p->next=g->vexs[i].first; g->vexs[i].first=p; } } int visited[VSIZE]; void (*visitFunc)(VType t); void print(VType t) { printf("%d\n",t); } void DFS(AdjMGraph g,int i) { visited[i]=1; visitFunc(g.vexs[i].data); ENode *p=g.vexs[i].first; while(p) { if(visited[p->v]==0) DFS(g,p->v); p=p->next; } } void DFSTraverse(AdjMGraph g,void (*vf)(VType t)) { visitFunc=vf; for(int i=0;i<g.VNum;i++) { visited[i]=0; } for(int i=0;i<g.VNum;i++) { if(visited[j]==0) { DFS(g,j); } } } void main() { AdjMGraph g; //定義鄰接矩陣圖 creatAdjMGraph(&g); //建立鄰接矩陣圖 DFSTraverse(g,print); //遍歷鄰接矩陣圖 }
4.2 廣度優先搜索
4.2.1 鄰接矩陣
typedef int VType; //頂點的數據類型 typedef int EType; //邊的數據類型 #define VSIZE 100; //最大頂點數 typedef struct AdjMGraph { VType vex[VSIZE]; //頂點數組 EType arc[VSIZE][VSIZE]; //邊弧數組 int VNum; //頂點個數 int ENum; //邊弧的個數 }AdjMGraph; /* 建立鄰接矩陣 */ void creatAdjMGraph(AdjMGraph *g) { printf("輸入頂點個數:"); scanf("%d",&g->VNum); printf("輸入頂點間的邊數:"); scanf("%d",&g->ENum); for(int i=0;i<g->VNum;i++) scanf("%d",&g->vexs[i]); for(int i=0;i<g->VNum;i++) for(int j=0;j<g->VNum;j++) g->arc[i][j]=0; for(int k=0;k<g->ENum;k++) { printf("輸入邊(vi,vj)的下標i,j"); int i,j; scanf("%d %d",&i,&j); g->arc[i][j]=g->arc[j][i]=1; } } void print(VType t) { printf("%d\n",t); } void BFSTraverse(AdjMGraph g,void(*visitFunc)(VType t)) { int visited[VSIZE]; for(int i=0;i<g.VNum;i++) { visited[i]=0; } Queue q; initQueue(&q); for(int i=0;i<g.VNum;i++) { if(visited[i]==0) { visited[i]=1; visitFunc(g.vexs[i]); enQueue(&q,i); while(QueueEmpty(q)==0) { deQueue(&q,&i); for(int j=0;j<g.VNum;j++) { if(g.arc[i][j]==1 && visited[j]==0) { visited[j]==1; visitFunc(g.vexs[j]); enQueue(&q,j); } } } } } }
4.2.2 鄰接表
typedef int VType; //頂點的數據類型 typedef int EType; //邊的數據類型 #define VSIZE 100; //最大頂點數 typedef struct ENode //邊鏈表結點 { int v; //頂點下標 struct ENode *next; //下一個頂點的指針 }ENode; typedef struct VNode //頂點表結點 { VType data; //頂點中的數據 struct VNode *first; //第一個邊鏈表結點的指針 }VNode; typedef struct AdjMGraph { VType vex[VSIZE]; //頂點數組 int VNum; //頂點數 int ENum; //邊數 }AdjMGraph; /* 建立鄰接表 */ void creatAdjMGraph(AdjMGraph *g) { printf("輸入頂點個數:"); scanf("%d",&g->VNum); printf("輸入頂點間的邊數:"); scanf("%d",&g->ENum); for(int i=0;i<g->VNum;i++) { printf("輸入頂點%d的數據:",i); scanf("%d",&g->vexs[i].data); g->vexs[i].first=NULL; } for(int k=0;k<g->ENum;k++) { printf("輸入邊(vi,vj)的下標i,j"); int i,j; scanf("%d %d",&i,&j); ENode *p=(ENode*)malloc(sizeof(ENode)); p->v=j; p->next=g->vexs[i].first; g->vexs[i].first=p; p=(ENode*)malloc(sizeof(ENode)); p->v=i; p->next=g->vexs[i].first; g->vexs[i].first=p; } } void print(VType t) { printf("%d\n",t); } void DFSTraverse(AdjMGraph g,void(*visitFunc)(VType t)) { int visited[VSIZE]; for(int i=0;i<g.VNum;i++) { visited[i]=0; } Queue q; initQueue(&q); for(int i=0;i<g.VNum;i++) { if(visited[i]==0) { visited[i]=1; visitFunc(g.vexs[i].data); enQueue(&q,i); while(QueueEmpty(q)==0) { deQueue(&q,&i); ENode *p=g.vexs[i].first; while(p) { if(visited[p->v]==0) { visited[p->v]==1; visitFunc(g.vexs[p->v].data); enQueue(&q,p->v); } p=p->next; } } } } } void main() { AdjMGraph g; //定義鄰接矩陣圖 creatAdjMGraph(&g); //建立鄰接矩陣圖 DFSTraverse(g,print); //遍歷鄰接矩陣圖 }