浅谈数据结构之图的邻接矩阵深度和广度优先遍历(八)

   图:是由顶点的有穷非空集合和顶点之间边的集合组成,通常表示为:G(V,E),其中,G表示一个图,V是图G中顶点的集合,E是图G中边的集合。注意:(1).线性表中我们把数据元素叫元素,树中将数据元素叫结点,而图中数据元素,我们一般称之为顶点;(2).在图结构中,不允许没有顶点,在定义中,若V是顶点的集合,则强调了顶点集合V有穷非空;(3).线性表中,相邻的元素之间具有线性关系,树结构中,相邻两层的结点具有层次关系,而图中,任意两个顶点之间都可能有关系,顶点之间的逻辑关系用边来表示,边的集合可以是空的。

  图按照有无方向分为有向图和无向图,无向图由顶点和边构成,有向图由顶点和弧构成,弧有弧头和弧尾之分。由于图的结构比较复杂,任意两个顶点之间都可能存在联系,因此无法以数据元素在内存中的物理位置来表示元素之间的关系,也就是说,图不可能用简单的顺序存储结构来表示,而多重链表的的方式,即以一个数据域和多个指针域组成的结点表示图中的一个顶点,尽管可以实现图结构,但还是有很多问题的。

  考虑到图是由顶点和边或弧两部分组成的,而边或弧又是顶点与顶点之间的关系,所以可以用两个数组来表示图,一个以为数组存储图中顶点的信息,另一个二维数组存储图中边或弧的信息,其中这个二维数组我们一般称之为邻接矩阵。

  图的遍历和树的遍历类似,是从图中某一顶点出发访遍其余顶点,且使每一个顶点仅被访问一次,这一过程就叫做图的遍历。图的遍历又分为深度优先遍历和广度优先遍历,深度优先遍历像是一棵树的前序遍历,而广度优先遍历就类似于一棵树的层序遍历。

图的创建及邻接矩阵深度和广度优先遍历源程序代码如下所示:

  1 #include <stdio.h>
  2 #include <stdlib.h>
  3 
  4 #define OK 1
  5 #define ERROR 0
  6 #define TRUE 1
  7 #define FALSE 0
  8 
  9 typedef int Status;           /* Status是函数的类型,其值是函数结果状态代码,如OK等 */  
 10 typedef int Boolean;          /* Boolean是布尔类型,其值是TRUE或FALSE */
 11 
 12 typedef char VertexType;      /* 顶点类型应由用户定义 */
 13 typedef int EdgeType;         /* 边上的权值类型应由用户定义 */
 14 
 15 #define MAXSIZE 9             /* 存储空间初始分配量 */
 16 #define MAXEDGE 15
 17 #define MAXVEX 9
 18 #define INFINITY 65535
 19 
 20 typedef struct
 21 {
 22     VertexType vexs[MAXVEX];         /* 顶点表 */
 23     EdgeType arc[MAXVEX][MAXVEX];    /* 邻接矩阵,可看作边表 */
 24     int numVertexes, numEdges;       /* 图中当前的顶点数和边数 */ 
 25 }MGraph;
 26 
 27 /* 循环队列的顺序存储结构 */
 28 typedef struct
 29 {
 30     int data[MAXSIZE];
 31     int front;             /* 头指针 */
 32     int rear;              /* 尾指针,若队列不空,指向队列尾元素的下一个位置 */
 33 }Queue;
 34 
 35 /* 初始化一个空队列Q */
 36 Status InitQueue(Queue *Q)
 37 {
 38     Q->front=0;
 39     Q->rear=0;
 40     return  OK;
 41 }
 42 
 43 /* 若队列Q为空队列,则返回TRUE,否则返回FALSE */
 44 Status QueueEmpty(Queue Q)
 45 { 
 46     if(Q.front==Q.rear)         /* 队列空的标志 */
 47         return TRUE;
 48     else
 49         return FALSE;
 50 }
 51 
 52 /* 若队列未满,则插入元素e为Q新的队尾元素 */
 53 Status EnQueue(Queue *Q,int e)
 54 {
 55     if ((Q->rear+1)%MAXSIZE == Q->front)        /* 队列满的判断 */
 56         return ERROR;
 57     Q->data[Q->rear]=e;                    /* 将元素e赋值给队尾 */
 58     Q->rear=(Q->rear+1)%MAXSIZE;           /* rear指针向后移一位置, */
 59                                            /* 若到最后则转到数组头部 */
 60     return  OK;
 61 }
 62 
 63 /* 若队列不空,则删除Q中队头元素,用e返回其值 */
 64 Status DeQueue(Queue *Q,int *e)
 65 {
 66     if (Q->front == Q->rear)            /* 队列空的判断 */
 67         return ERROR;
 68     *e=Q->data[Q->front];               /* 将队头元素赋值给e */
 69     Q->front=(Q->front+1)%MAXSIZE;      /* front指针向后移一位置, */
 70                                         /* 若到最后则转到数组头部 */
 71     return  OK;
 72 }
 73 
 74 void CreateMGraph(MGraph *G)
 75 {
 76     int i, j;
 77 
 78     G->numEdges=15;
 79     G->numVertexes=9;
 80 
 81     /* 读入顶点信息,建立顶点表 */
 82     G->vexs[0]='A';
 83     G->vexs[1]='B';
 84     G->vexs[2]='C';
 85     G->vexs[3]='D';
 86     G->vexs[4]='E';
 87     G->vexs[5]='F';
 88     G->vexs[6]='G';
 89     G->vexs[7]='H';
 90     G->vexs[8]='I';
 91 
 92     for (i = 0; i < G->numVertexes; i++)        /* 初始化图 */
 93     {
 94         for ( j = 0; j < G->numVertexes; j++)
 95         {
 96             G->arc[i][j]=0;
 97         }
 98     }
 99 
100     G->arc[0][1]=1;
101     G->arc[0][5]=1;
102 
103     G->arc[1][2]=1; 
104     G->arc[1][8]=1; 
105     G->arc[1][6]=1; 
106     
107     G->arc[2][3]=1; 
108     G->arc[2][8]=1; 
109     
110     G->arc[3][4]=1;
111     G->arc[3][7]=1;
112     G->arc[3][6]=1;
113     G->arc[3][8]=1;
114 
115     G->arc[4][5]=1;
116     G->arc[4][7]=1;
117 
118     G->arc[5][6]=1; 
119     
120     G->arc[6][7]=1; 
121 
122     for(i = 0; i < G->numVertexes; i++)
123     {
124         for(j = i; j < G->numVertexes; j++)
125         {
126             G->arc[j][i] =G->arc[i][j];
127         }
128     }
129 }
130  
131 Boolean visited[MAXVEX];     /* 访问标志的数组 */
132 
133 /* 邻接矩阵的深度优先递归算法 */
134 void DFS(MGraph G, int i)
135 {
136     int j;
137      visited[i] = TRUE;
138      printf("%c ", G.vexs[i]);        /* 打印顶点,也可以其它操作 */
139     for(j = 0; j < G.numVertexes; j++)
140         if(G.arc[i][j] == 1 && !visited[j])
141              DFS(G, j);               /* 对为访问的邻接顶点递归调用 */
142 }
143 
144 /* 邻接矩阵的深度遍历操作 */
145 void DFSTraverse(MGraph G)
146 {
147     int i;
148      for(i = 0; i < G.numVertexes; i++)
149          visited[i] = FALSE;         /* 初始所有顶点状态都是未访问过状态 */
150     for(i = 0; i < G.numVertexes; i++)
151          if(!visited[i])             /* 对未访问过的顶点调用DFS,若是连通图,只会执行一次 */ 
152             DFS(G, i);
153 }
154 
155 /* 邻接矩阵的广度遍历算法 */
156 void BFSTraverse(MGraph G)
157 {
158     int i, j;
159     Queue Q;
160     for(i = 0; i < G.numVertexes; i++)
161            visited[i] = FALSE;
162     InitQueue(&Q);                      /* 初始化一辅助用的队列 */
163     for(i = 0; i < G.numVertexes; i++)  /* 对每一个顶点做循环 */
164     {
165         if (!visited[i])                /* 若是未访问过就处理 */
166         {
167             visited[i]=TRUE;            /* 设置当前顶点访问过 */
168             printf("%c ", G.vexs[i]);          /* 打印顶点,也可以其它操作 */
169             EnQueue(&Q,i);              /* 将此顶点入队列 */
170             while(!QueueEmpty(Q))       /* 若当前队列不为空 */
171             {
172                 DeQueue(&Q,&i);         /* 将队对元素出队列,赋值给i */
173                 for(j=0;j<G.numVertexes;j++) 
174                 { 
175                     /* 判断其它顶点若与当前顶点存在边且未访问过  */
176                     if(G.arc[i][j] == 1 && !visited[j]) 
177                     { 
178                          visited[j]=TRUE;            /* 将找到的此顶点标记为已访问 */
179                         printf("%c ", G.vexs[j]);    /* 打印顶点 */
180                         EnQueue(&Q,j);               /* 将找到的此顶点入队列  */
181                     } 
182                 } 
183             }
184         }
185     }
186 }
187 
188 
189 int main(void)
190 {    
191     MGraph G;
192     CreateMGraph(&G);
193     
194     printf("\n1.图的邻接矩阵的深度优先遍历为:");
195     DFSTraverse(G);
196     
197     printf("\n2.图的邻接矩阵的广度优先遍历为:");
198     BFSTraverse(G);
199     
200     return 0;
201 }

 

posted @ 2017-01-01 21:03  连城无忧  阅读(1411)  评论(0编辑  收藏  举报