数据结构–图
图是研究数据元素之间的多对多的关系。在这种结构中,任意两个元素之间可能存在关系。即结点之间的关系可以是任意的,图中任意元素之间都可能相关。图的应用极为广泛,已渗入到诸如语言学、逻辑学、物理、化学、电讯、计算机科学以及数学的其它分支。
图的定义
一个图(G)定义为一个偶对(V,E) ,记为G=(V,E) 。其中: V是顶(Vertex)的非空有限集合,记为V(G);E是无序集V&V的一个子集,记为E(G) ,其元素是图的弧(Arc)。将顶点集合为空的图称为空图。其形式化定义为:G=(V ,E),V={v|v in data object},
E={(v,w)| v,w in V and p(v,w)},P(v,w)表示从顶点v到顶点w有一条直接通路。
图的结构
图的存储结构比较复杂,其复杂性主要表现在:
任意顶点之间可能存在联系,无法以数据元素在存储区中的物理位置来表示元素之间的关系。
图中顶点的度不一样,有的可能相差很大,若按度数最大的顶点设计结构,则会浪费很多存储单元,反之按每个顶点自己的度设计不同的结构,又会影响操作。
图的常用的存储结构有:邻接矩阵、邻接链表、十字链表、邻接多重表和边表。
在图的邻接链表表示中,所有顶点结点用一个向量 以顺序结构形式存储,可以随机访问任意顶点的链表,该向量称为表头向量,向量的下标指示顶点的序号。
用邻接链表存储图时,对无向图,其邻接链表是唯一的,对有向图,其邻接链表有两种形式。
图的遍历
深度优先搜索(DFS):深度优先搜索(Depth First Search–DFS)遍历类似树的先序遍历,是树的先序遍历的推广。
设初始状态时图中的所有顶点未被访问,则:
⑴ :从图中某个顶点vi出发,访问vi;然后找到vi的一个邻接顶点vi1 ;
⑵:从vi1出发,深度优先搜索访问和vi1相邻接且未被访问的所有顶点;
⑶:转⑴ ,直到和vi相邻接的所有顶点都被访问为止
⑷ :继续选取图中未被访问顶点vj作为起始顶点,转(1),直到图中所有顶点都被访问为止。
广度优先搜索(BFS):广度优先搜索(Breadth First Search–BFS)遍历类似树的按层次遍历的过程。
设初始状态时图中的所有顶点未被访问,则:
⑴ :从图中某个顶点vi出发,访问vi;
⑵:访问vi的所有相邻接且未被访问的所有顶点vi1,vi2,…,vim;
⑶:以vi1,vi2, …,vim的次序,以vij(1≦j≦m)依此作为vi ,转⑴;
⑷ :继续选取图中未被访问顶点vk作为起始顶点,转⑴,直到图中所有顶点都被访问为止。
代码实现–C语言实现
Graph.c
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "Queue.h"
#define MAX_VERTEX_NUM 10
#define INFINITY 32768
typedef enum{DG,DN,UDG,UDN} GraphKind;
#define ERROR 0
#define TRUE 1
typedef int status;
typedef char ElemType;
typedef struct MNode{
ElemType vertex[MAX_VERTEX_NUM]; /*顶点*/
int Arc[MAX_VERTEX_NUM][MAX_VERTEX_NUM]; /*弧*/
int vexnum,arcnum; /*弧个数,顶点个数*/
GraphKind kind;
}GraphNode,*Graph;
int IsRead[MAX_VERTEX_NUM]; //标记顶点是否被遍历过
/*初始化*/
status Init(Graph *G){
(*G) = (GraphNode *)malloc(sizeof(GraphNode));
(*G)->vexnum = 0;
(*G)->arcnum = 0;
if((*G))return TRUE;
else{
printf("初始化出错...\n");
}
return ERROR;
}
/*查找位置*/
void FindPos(Graph G,char a,char b,int *pos1,int *pos2){
int i = 0;
*pos1 = -1; *pos2 = -1; //初值
for(i = 0; i<G->vexnum;i++){
if(G->vertex[i]==a){
(*pos1) = i;
continue;
}else if(G->vertex[i] == b){
(*pos2) = i;
continue;
}
}
}
/*建立图*/
void BuildGraph(Graph G){
int choice = 0,num = 0,pos1,pos2,i,j,weight;
char a,b,ch;
printf("请选择建立的图的类型:1:有向图,2:有向网,3:无向图,无向网:\n");
scanf("%d",&choice);
getchar();
printf("\n"); //下一行
if(choice == 1){ //有向图
for(i = 0;i<MAX_VERTEX_NUM;i++){ //初始化弧
for(j = 0;j<MAX_VERTEX_NUM;j++){
G->Arc[i][j] = 0;
}
}
G->kind = DG; //设置图的类型
printf("请输入顶点(不超过10个,以#结束):\n");
scanf("%c",&ch);
while(ch!='#' && num <10){
G->vertex[num] = ch;
scanf("%c",&ch);
num++;
}
G->vexnum = num; //顶点个数
getchar(); //清除键盘缓冲区
printf("请输入对应的弧以a->b格式输入(以#->#结束):\n");
scanf("%c->%c",&a,&b);
while(a!='#' && b!='#'){
printf("%c,%c",a,b);
FindPos(G,a,b,&pos1,&pos2);
printf("位置a:%d,位置b:%d\n",pos1,pos2);
if(pos1!= -1 && pos2!= -1){ //忽略不存在的顶点
G->Arc[pos1][pos2] = 1;
G->arcnum++;
}
scanf("%c->%c",&a,&b);
}
getchar(); //清空
}
else if(choice==2){ //有向网
num = 0; //个数初始化
for(i = 0;i < MAX_VERTEX_NUM; i++){ //初始化弧
for(j = 0;j<MAX_VERTEX_NUM; j++){
G->Arc[i][j] = INFINITY;
}
}
G->kind = DN; //设置图的类型
printf("请输入顶点(不超过10个,以#结束):\n");
scanf("%c",&ch);
while(ch!='#' && num <10){
G->vertex[num] = ch;
scanf("%c",&ch);
num++;
}
G->vexnum = num; //顶点个数
getchar(); //清除键盘缓冲区
printf("请输入对应的弧以a->b:weight格式输入(以#->#:0结束):\n");
scanf("%c->%c:%d",&a,&b,&weight);
while(a!='#' && b!='#'){
printf("%c,%c",a,b);
FindPos(G,a,b,&pos1,&pos2);
printf("位置a:%d,位置b:%d\n",pos1,pos2);
if(pos1!= -1 && pos2!= -1){ //忽略不存在的顶点
G->Arc[pos1][pos2] = weight;
G->arcnum++;
}
scanf("%c->%c:%d",&a,&b,&weight);
}
getchar(); //清空
}
else if(choice == 3){//无向图
num = 0;
for(i = 0;i<MAX_VERTEX_NUM;i++){ //初始化弧
for(j = 0;j<MAX_VERTEX_NUM;j++){
G->Arc[i][j] = 0;
}
}
G->kind = UDG; //设置图的类型
printf("请输入顶点(不超过10个,以#结束):\n");
scanf("%c",&ch);
while(ch!='#' && num <10){
G->vertex[num] = ch;
scanf("%c",&ch);
num++;
}
G->vexnum = num; //顶点个数
getchar(); //清除键盘缓冲区
printf("请输入对应的弧以a-b格式输入(以#-#结束):\n");
scanf("%c-%c",&a,&b);
while(a!='#' && b!='#'){
printf("%c,%c",a,b);
FindPos(G,a,b,&pos1,&pos2);
printf("位置a:%d,位置b:%d\n",pos1,pos2);
if(pos1!= -1 && pos2!= -1){ //忽略不存在的顶点
G->Arc[pos1][pos2] = 1;
G->Arc[pos2][pos1] = 1;
G->arcnum++;
}
scanf("%c-%c",&a,&b);
}
getchar(); //清空
}
else if(choice == 4){ //无向网
num = 0; //个数初始化
for(i = 0;i < MAX_VERTEX_NUM; i++){ //初始化弧
for(j = 0;j<MAX_VERTEX_NUM; j++){
G->Arc[i][j] = INFINITY;
}
}
G->kind = DN; //设置图的类型
printf("请输入顶点(不超过10个,以#结束):\n");
scanf("%c",&ch);
while(ch!='#' && num <10){
G->vertex[num] = ch;
scanf("%c",&ch);
num++;
}
G->vexnum = num; //顶点个数
getchar(); //清除键盘缓冲区
printf("请输入对应的弧以a-b:weight格式输入(以#-#:0结束):\n");
scanf("%c->%c:%d",&a,&b,&weight);
while(a!='#' && b!='#'){
printf("%c,%c",a,b);
FindPos(G,a,b,&pos1,&pos2);
printf("位置a:%d,位置b:%d\n",pos1,pos2);
if(pos1!= -1 && pos2!= -1){ //忽略不存在的顶点
G->Arc[pos1][pos2] = weight;
G->Arc[pos2][pos1] = weight;
G->arcnum++;
}
scanf("%c-%c:%d",&a,&b,&weight);
}
getchar(); //清空
}
else { //非法输入的选择
printf("输入非法,请输入正确的数字!!\n");
return;
}
}
void DepthFS(Graph G,int pos){ /*深度优先搜索for图*/
int i = 0,j = 0;
if(IsRead[pos] == 0){
IsRead[pos] = 1; //从第一个开始
printf("遍历顶点%c\n",G->vertex[pos]);
}
for(i = 0;i<G->vexnum;i++){
if(G->Arc[pos][i] == 1 && IsRead[i] ==0){ //存在弧
DepthFS(G,i);
}
}
}
void DepthFS1(Graph G,int pos){ /*深度优先搜索for网*/
int i = 0,j = 0;
if(IsRead[pos] == 0){
IsRead[pos] = 1; //从第一个开始
printf("遍历顶点%c\n",G->vertex[pos]);
}
for(i = 0;i<G->vexnum;i++){
if(G->Arc[pos][i] !=INFINITY && IsRead[i] ==0){ //存在弧且未被遍历
DepthFS1(G,i);
}
}
}
/*深度优先搜索*/
void DFS(Graph G){
if(G->kind == DG || G->kind == UDG){ //图
DepthFS(G,0);
}else if(G->kind == DN || G->kind == UDN){ //网
DepthFS1(G,0);
}
}
void BFS1(Graph G,int pos){ //广度优先搜索for图
int i = 0,temp;
Queue Q;
InitQueue(&Q);
for(i = 0; i <G->vexnum;i++){ //清零
IsRead[i] = 0;
}
if(IsRead[pos] ==0){
IsRead[pos] = 1;
printf("遍历顶点:%c\n",G->vertex[pos]);
}
EnterQueue(Q,pos);
while(!isEmpty(Q)){//当队列不为空
OutQueue(Q,&temp);
for(i = 0; i< G->vexnum;i++){
if(G->Arc[temp][i] == 1 && IsRead[i] == 0){
IsRead[i] = 1;
printf("遍历顶点:%c\n",G->vertex[i]);
EnterQueue(Q,i);
}
}
}
free(Q);
}
void BFS2(Graph G,int pos){ //广度优先搜索for图
int i = 0,temp;
Queue Q;
InitQueue(&Q);
for(i = 0; i <G->vexnum;i++){ //清零
IsRead[i] = 0;
}
if(IsRead[pos] ==0){
IsRead[pos] = 1;
printf("遍历顶点:%c\n",G->vertex[pos]);
}
EnterQueue(Q,pos);
while(!isEmpty(Q)){//当队列不为空
OutQueue(Q,&temp);
for(i = 0; i< G->vexnum;i++){
if(G->Arc[temp][i] != INFINITY && IsRead[i] == 0){
IsRead[i] = 1;
printf("遍历顶点:%c\n",G->vertex[i]);
EnterQueue(Q,i);
}
}
}
free(Q);
}
void BFS(Graph G){
if(G->kind == DG || G->kind == UDG){ //图
BFS1(G,0);
}else if(G->kind == DN || G->kind == UDN){ //网
BFS2(G,0);
}
}
void main(){
int i = 0;
Graph G = NULL;
Init(&G);
BuildGraph(G);
for(i = 0; i<MAX_VERTEX_NUM; i++){
IsRead[i] = 0; //未被遍历
}
printf("\n深度优先搜索:\n");
DFS(G,0);
printf("\n广度优先搜索:\n");
BFS(G,0);
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
- 114
- 115
- 116
- 117
- 118
- 119
- 120
- 121
- 122
- 123
- 124
- 125
- 126
- 127
- 128
- 129
- 130
- 131
- 132
- 133
- 134
- 135
- 136
- 137
- 138
- 139
- 140
- 141
- 142
- 143
- 144
- 145
- 146
- 147
- 148
- 149
- 150
- 151
- 152
- 153
- 154
- 155
- 156
- 157
- 158
- 159
- 160
- 161
- 162
- 163
- 164
- 165
- 166
- 167
- 168
- 169
- 170
- 171
- 172
- 173
- 174
- 175
- 176
- 177
- 178
- 179
- 180
- 181
- 182
- 183
- 184
- 185
- 186
- 187
- 188
- 189
- 190
- 191
- 192
- 193
- 194
- 195
- 196
- 197
- 198
- 199
- 200
- 201
- 202
- 203
- 204
- 205
- 206
- 207
- 208
- 209
- 210
- 211
- 212
- 213
- 214
- 215
- 216
- 217
- 218
- 219
- 220
- 221
- 222
- 223
- 224
- 225
- 226
- 227
- 228
- 229
- 230
- 231
- 232
- 233
- 234
- 235
- 236
- 237
- 238
- 239
- 240
- 241
- 242
- 243
- 244
- 245
- 246
- 247
- 248
- 249
- 250
- 251
- 252
- 253
- 254
- 255
- 256
- 257
- 258
- 259
- 260
- 261
- 262
- 263
- 264
- 265
- 266
- 267
- 268
- 269
- 270
- 271
- 272
- 273
- 274
- 275
- 276
- 277
- 278
- 279
- 280
- 281
- 282
- 283
- 284
- 285
- 286
- 287
- 288
- 289
- 290
- 291
- 292
- 293
- 294
- 295
- 296
- 297
- 298
- 299
- 300
- 301
- 302
- 303
- 304
- 305
- 306
- 307
- 308
- 309
- 310
- 311
- 312
- 313
- 314
- 315
- 316
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
- 114
- 115
- 116
- 117
- 118
- 119
- 120
- 121
- 122
- 123
- 124
- 125
- 126
- 127
- 128
- 129
- 130
- 131
- 132
- 133
- 134
- 135
- 136
- 137
- 138
- 139
- 140
- 141
- 142
- 143
- 144
- 145
- 146
- 147
- 148
- 149
- 150
- 151
- 152
- 153
- 154
- 155
- 156
- 157
- 158
- 159
- 160
- 161
- 162
- 163
- 164
- 165
- 166
- 167
- 168
- 169
- 170
- 171
- 172
- 173
- 174
- 175
- 176
- 177
- 178
- 179
- 180
- 181
- 182
- 183
- 184
- 185
- 186
- 187
- 188
- 189
- 190
- 191
- 192
- 193
- 194
- 195
- 196
- 197
- 198
- 199
- 200
- 201
- 202
- 203
- 204
- 205
- 206
- 207
- 208
- 209
- 210
- 211
- 212
- 213
- 214
- 215
- 216
- 217
- 218
- 219
- 220
- 221
- 222
- 223
- 224
- 225
- 226
- 227
- 228
- 229
- 230
- 231
- 232
- 233
- 234
- 235
- 236
- 237
- 238
- 239
- 240
- 241
- 242
- 243
- 244
- 245
- 246
- 247
- 248
- 249
- 250
- 251
- 252
- 253
- 254
- 255
- 256
- 257
- 258
- 259
- 260
- 261
- 262
- 263
- 264
- 265
- 266
- 267
- 268
- 269
- 270
- 271
- 272
- 273
- 274
- 275
- 276
- 277
- 278
- 279
- 280
- 281
- 282
- 283
- 284
- 285
- 286
- 287
- 288
- 289
- 290
- 291
- 292
- 293
- 294
- 295
- 296
- 297
- 298
- 299
- 300
- 301
- 302
- 303
- 304
- 305
- 306
- 307
- 308
- 309
- 310
- 311
- 312
- 313
- 314
- 315
- 316
Queue.h
#include <stdio.h>
#include <stdlib.h>
#define TRUE 1
#define ERROR 0
#define MAX_SIZE 20
typedef int status;
/*定义队列*/
typedef struct QNode{
int Qarr[MAX_SIZE];
int tail,head;
int size;
}QNode,*Queue;
void InitQueue(Queue *Q){
(*Q) = (QNode *)malloc(sizeof(QNode));
if(*Q){
(*Q)->size = 0;
(*Q)->head = 0;
(*Q)->tail = 0;
}
}
/*入队列*/
void EnterQueue(Queue Q, int data){
if((Q->tail +1) % MAX_SIZE == Q->head){
printf("队列已经满!!\n");
return;
}
Q->Qarr[Q->tail] = data;
Q->size++;
Q->tail = (Q->tail +1) % MAX_SIZE;
return;
}
void OutQueue(Queue Q, int *data){
if(Q->head == Q->tail){
printf("队列为空!!\n");
return;
}
(*data) = Q->Qarr[Q->head];
Q->size--;
Q->head = (Q->head +1) % MAX_SIZE;
return;
}
int isEmpty(Queue Q){
if(Q->head == Q->tail)return 1;
return 0;
}