图的创建与遍历
图是非线性结构,有两种存储结构,一种是邻接矩阵,另一种是邻接表。
邻接矩阵用一个二维数组来表示。
代码如下:
1 #include<stdio.h> 2 #include<stdlib.h> 3 #define max_len 100 4 5 typedef struct node{ 6 int num; //下标 7 int data; //数据 8 }Point; //节点类型 9 10 typedef struct{ 11 int pointNum; //顶点数 12 int edgeNum; //边数 13 Point pointArray[max_len]; //用数组来存放顶点 14 int edgeArray[max_len][max_len]; //用数组来存放边 15 }AdjMatrix; //矩阵类型 16 17 AdjMatrix *create_AdjMatrix(){ 18 19 AdjMatrix *adjMatrix = (AdjMatrix *)malloc(sizeof(AdjMatrix)); 20 21 int i,j,n; 22 printf("输入顶点数:"); 23 scanf("%d",&i); 24 printf("输入边数:"); 25 scanf("%d",&j); 26 27 adjMatrix->pointNum = i; 28 adjMatrix->edgeNum = j; 29 30 for(i=0;i<adjMatrix->pointNum;i++){ 31 adjMatrix->pointArray[i].data = i; 32 adjMatrix->pointArray[i].num = i; 33 } 34 35 for(i=0;i<adjMatrix->pointNum;i++) 36 for(j=0;j<adjMatrix->pointNum;j++) 37 adjMatrix->edgeArray[i][j] = 0; 38 39 printf("输入边的信息:"); 40 for(i=0;i<adjMatrix->edgeNum;i++){ 41 scanf("%d %d",&j,&n); 42 adjMatrix->edgeArray[j][n] = 1; 43 } 44 45 return adjMatrix; 46 } 47 48 void display(AdjMatrix *adjMatrix){ 49 50 printf("\n"); 51 52 int i,j; 53 for(i=0;i<adjMatrix->pointNum;i++){ 54 for(j=0;j<adjMatrix->pointNum;j++) 55 printf("%d ",adjMatrix->edgeArray[i][j]); 56 printf("\n"); 57 } 58 59 } 60 61 void main(){ 62 63 AdjMatrix *adjMatrix = create_AdjMatrix(); 64 display(adjMatrix); 65 66 }
邻接表用链表数组来表示,即链表数组中的每一个元素都是一个链表的头结点,然后这个头结点后面就会跟着一串的链节点,用来表示头结点代表的图中元素可以直接到达链节点代表的图中元素。
代码如下:
1 #include<stdio.h> 2 #include<stdlib.h> 3 #define max_len 100 4 5 typedef struct node{ 6 int adjvex; 7 int data; 8 struct node *nextarc; 9 }ARCnode; //节点类型 10 11 typedef struct{ 12 int vexdata; 13 ARCnode *firstarc; 14 }VEXnode; //头结点类型 15 16 typedef struct{ 17 int pointNum; //顶点数 18 int edgeNum; //边数 19 VEXnode vexnode[max_len]; //头结点数组 20 }ALGraph; //邻接表类型 21 22 23 ALGraph *create_ALGraph(){ 24 25 ALGraph *algraph = (ALGraph *)malloc(sizeof(ALGraph)); 26 ARCnode *arcnode; 27 28 int i,j,n; 29 printf("输入顶点数:"); 30 scanf("%d",&i); 31 printf("输入边数:"); 32 scanf("%d",&j); 33 34 algraph->pointNum = i; 35 algraph->edgeNum = j; 36 37 38 for(i=0;i<algraph->edgeNum;i++){ 39 algraph->vexnode[i].vexdata = i; 40 algraph->vexnode[i].firstarc = NULL; 41 } 42 43 printf("输入边的信息:"); 44 for(i=0;i<algraph->edgeNum;i++){ 45 scanf("%d %d",&j,&n); 46 arcnode = (ARCnode *)malloc(sizeof(ARCnode)); 47 arcnode->adjvex = n; 48 arcnode->data = n; 49 arcnode->nextarc = algraph->vexnode[j].firstarc; 50 algraph->vexnode[j].firstarc = arcnode; 51 } 52 53 return algraph; 54 } 55 56 void display(ALGraph *algraph){ 57 58 ARCnode *arcnode; 59 60 int i; 61 for(i=0;i<algraph->edgeNum;i++){ 62 printf("%d ",algraph->vexnode[i].vexdata); 63 arcnode = algraph->vexnode[i].firstarc; 64 while(arcnode!=NULL){ 65 printf("%d ",arcnode->adjvex); 66 arcnode = arcnode->nextarc; 67 } 68 printf("\n"); 69 } 70 71 } 72 73 void main(){ 74 75 ALGraph *algraph = create_ALGraph(); 76 display(algraph); 77 78 }
深度优先遍历
算法:首先访问某个顶点V1,然后访问与v1邻接的顶点V2,再访问与v2邻接的顶点V3,然后不断重复,直到邻接的顶点vi被访问过,然后退回到Vi-1,访问Vi-1没被访问过的邻接点,再不断重复这两个过程即可访问完所有节点
代码如下:
1 #include<stdio.h> 2 #include<stdlib.h> 3 #define max_len 100 4 int visited[max_len]; 5 6 typedef struct node{ 7 int adjvex; 8 struct node *nextarc; 9 int info; 10 }ARCnode; 11 12 13 typedef struct vexnode{ 14 int vexdata; 15 ARCnode *firstarc; 16 }VEXnode; 17 18 typedef struct{ 19 VEXnode vexnode[max_len]; 20 int vexnum,arcnum; 21 }ALGraph; 22 23 24 ALGraph *create_ALGraph(){ 25 26 int i,j,n; 27 ALGraph *a = (ALGraph *)malloc(sizeof(ALGraph)); 28 ARCnode *p; 29 30 printf("输入顶点数:\n"); 31 scanf("%d",&j); 32 printf("输入边数:\n"); 33 scanf("%d",&n); 34 35 a->vexnum = j; 36 a->arcnum = n; 37 38 for(i=0;i<a->vexnum;i++){ 39 a->vexnode[i].vexdata = i; 40 a->vexnode[i].firstarc = NULL; 41 } 42 43 printf("\n"); 44 printf("输入边的信息:\n"); 45 for(i=0;i<a->arcnum;i++){ 46 scanf("%d %d",&j,&n); 47 p = (ARCnode *)malloc(sizeof(ARCnode)); 48 p->adjvex = n; 49 p->info = n; 50 p->nextarc = a->vexnode[j].firstarc; 51 a->vexnode[j].firstarc = p; 52 } 53 54 return a; 55 } 56 57 //深度优先遍历使用递归来遍历所有节点 58 void dfs(ALGraph a,int v){ 59 60 visited[v] = 1; //访问过的顶点标识为1 61 printf("%d ",v); 62 VEXnode vex = a.vexnode[v]; 63 ARCnode *arc = vex.firstarc; 64 while(arc!=NULL){ 65 if(visited[arc->adjvex]==0)//判断是否访问过 66 dfs(a,arc->adjvex); //访问该顶点的邻接点 67 arc = arc->nextarc; //如果访问过,则退回到该节点,寻找没有被访问过的节点 68 } 69 70 } 71 72 //深度优先遍历函数 73 void dfs_trave(ALGraph a){ 74 75 int i; 76 for(i=0;i<a.vexnum;i++) 77 visited[i] = 0; //标识数组,用来记录被访问过的顶点 78 //0代表没有访问过,1则反之 79 for(i=0;i<a.vexnum;i++) 80 if(visited[i] == 0) 81 dfs(a,i); 82 83 } 84 85 void display(ALGraph *a){ 86 87 printf("\n"); 88 89 int i,j; 90 for(i=0;i<a->vexnum;i++){ 91 j = a->vexnode[i].vexdata; 92 printf("%d ",j); 93 ARCnode *arc = a->vexnode[i].firstarc; 94 while(arc!=NULL){ 95 printf("%d ",arc->adjvex); 96 arc = arc->nextarc; 97 } 98 printf("\n"); 99 } 100 101 } 102 103 void main(){ 104 105 ALGraph *a = create_ALGraph(); 106 display(a); 107 // ALGraph alg = *a; 108 // dfs_trave(alg); 109 110 }
广度优先遍历
算法:访问某个顶点V1,然后把V1的所有邻接点全部访问,比如有V2、V3、V4。这就是一层,然后再访问V2的所有邻接点,接着访问V3、V4的所有邻接点。当然访问过的顶点不再需要访问了。
代码如下:广度遍历需要一个队列来暂时存储访问过得顶点。然后根据这个顶点来访问他的所有邻接点。
1 #include<stdio.h> 2 #include<stdlib.h> 3 #define max_len 100 4 int visited[max_len]; 5 6 typedef struct{ 7 int data[max_len]; 8 int front,rear; 9 }SeqQueue; 10 11 typedef struct node{ 12 int adjvex; 13 struct node *nextarc; 14 int info; 15 }ARCnode; 16 17 typedef struct vexnode{ 18 int vexdata; 19 ARCnode *firstarc; 20 }VEXnode; 21 22 typedef struct{ 23 VEXnode vexnode[max_len]; 24 int vexnum,arcnum; 25 }AlGraph; 26 27 SeqQueue *init_SeqQueue(){ 28 29 SeqQueue *sq = (SeqQueue *)malloc(sizeof(SeqQueue)); 30 sq->front = 0; 31 sq->rear = 0; 32 33 return sq; 34 } 35 36 int isEmpty(SeqQueue *sq){ 37 38 if(sq->front==sq->rear) 39 return 1; 40 return 0; 41 42 } 43 44 int delQueue(SeqQueue *sq){ 45 46 if(sq->rear==sq->front) 47 return ; 48 sq->rear = (sq->rear+1)%max_len; 49 return sq->data[sq->rear]; 50 51 } 52 53 void inQueue(SeqQueue *sq,int n){ 54 55 56 sq->front = (sq->front+1)%max_len; 57 if(sq->rear==sq->front) 58 return ; 59 sq->data[sq->front] = n; 60 61 } 62 63 AlGraph *create_AlGraph(){ 64 65 int i,j,n; 66 AlGraph *a = (AlGraph *)malloc(sizeof(AlGraph)); 67 ARCnode *p; 68 69 printf("输入顶点数:\n"); 70 scanf("%d",&j); 71 printf("输入边数:\n"); 72 scanf("%d",&n); 73 74 a->vexnum = j; 75 a->arcnum = n; 76 77 for(i=0;i<a->vexnum;i++){ 78 a->vexnode[i].vexdata = i; 79 a->vexnode[i].firstarc = NULL; 80 } 81 82 printf("\n"); 83 printf("输入边的信息:\n"); 84 for(i=0;i<a->arcnum;i++){ 85 scanf("%d %d",&j,&n); 86 p = (ARCnode *)malloc(sizeof(ARCnode)); 87 p->adjvex = n; 88 p->info = n; 89 p->nextarc = a->vexnode[j].firstarc; 90 a->vexnode[j].firstarc = p; 91 } 92 93 return a; 94 } 95 96 97 void bfs(AlGraph a,int v,SeqQueue *sq){ 98 99 printf("\n%d ",v); 100 visited[v] = 1; 101 inQueue(sq,v); //被访问过的顶点入队列 102 103 int i; 104 while(!isEmpty(sq)){ //如果队列非空则继续访问 105 i = delQueue(sq); //寻找出队顶点的所有邻接点 106 ARCnode *arc = a.vexnode[i].firstarc; 107 while(arc!=NULL){ 108 if(visited[arc->adjvex]!=1){ 109 printf("%d ",arc->adjvex); 110 visited[arc->adjvex] = 1; //标识为已被访问过 111 inQueue(sq,arc->adjvex); //被访问过的顶点入队列 112 } 113 arc = arc->nextarc; 114 } 115 } 116 117 } 118 119 //广度优先遍历函数 120 void bfs_trave(AlGraph a,SeqQueue *sq){ 121 122 int i; 123 for(i=0;i<a.vexnum;i++) 124 visited[i] = 0; 125 126 for(i=0;i<a.vexnum;i++){ 127 if(visited[i] == 0) 128 bfs(a,i,sq); 129 } 130 131 } 132 133 void display(AlGraph *a){ 134 135 printf("\n"); 136 137 int i,j; 138 for(i=0;i<a->vexnum;i++){ 139 j = a->vexnode[i].vexdata; 140 printf("%d ",j); 141 ARCnode *arc = a->vexnode[i].firstarc; 142 while(arc!=NULL){ 143 printf("%d ",arc->adjvex); 144 arc = arc->nextarc; 145 } 146 printf("\n"); 147 } 148 149 } 150 151 152 void main(){ 153 154 SeqQueue *sq = init_SeqQueue(); 155 AlGraph *a = create_AlGraph(); 156 display(a); 157 AlGraph alg = *a; 158 bfs_trave(alg,sq); 159 160 }