图的表示及遍历

图的表示方法通常有四种:

数组表示,邻接表,十字链表,邻接多重表。

邻接表是图的一种链式存储结构。

十字链表是有向图的另一种链式存储结构。

邻接多重表是无向图的一种链式存储结构。

====================================================

邻接表

邻接表中有两种节点,一种是头节点,另一种是表节点,头节点中存储一个顶点的数据和指向链表中的一个节点,表节点中存储当前顶点在图中的位置和指向下一条边或弧的节点,表头节点用链式或顺序结构方式存储,如下图所示就是上一篇文章G2无向图的邻接表表示。

=====================================================

遍历

深度优先搜索是树的先根遍历的推广,它的基本思想是:从图G的某个顶点v0出发,访问v0,然后选择一个与v0相邻且没被访问过的顶点vi访问,再从vi出发选择一个与vi相邻且未被访问的顶点vj进行访问,依次继续。如果当前被访问过的顶点的所有邻接顶点都已被访问,则退回到已被访问的顶点序列中最后一个拥有未被访问的相邻顶点的顶点w,从w出发按同样的方法向前遍历,直到图中所有顶点都被访问。

广度优先搜索是树的按层次遍历的推广,它的基本思想是:首先访问初始点vi,并将其标记为已访问过,接着访问vi的所有未被访问过的邻接点vi1,vi2,…, vin,并均标记已访问过,然后再按照vi1,vi2,…, vin的次序,访问每一个顶点的所有未被访问过的邻接点,并均标记为已访问过,依次类推,直到图中所有和初始点vi有路径相通的顶点都被访问过为止。

深度优先搜索:0->1->3->7->4->2->5->6

广度优先搜索:0->1->2->3->4->5->6->7

=======================================================

  1 // mytest.cpp : 定义控制台应用程序的入口点。
  2 //
  3 
  4 #include "stdafx.h"
  5 #include <stdio.h>
  6 #include <stdlib.h>
  7 
  8 #define TRUE 1
  9 #define FALSE 0
 10 #define OK 1
 11 #define ERROR 0
 12 #define OVERFLOW -2
 13 #define MAX_NUM 20
 14 
 15 typedef int Status;
 16 typedef int QElemType;
 17 typedef char VexType;
 18 
 19 /*
 20  * 邻接表存储结构
 21  */
 22 typedef struct EdgeNode
 23 {
 24     int adjvex;    //顶点的位置
 25     struct EdgeNode *next; //指向下一条边的指针
 26 }EdgeNode, *EdgeLink;
 27 
 28 typedef struct VexNode
 29 {
 30     VexType data;    //顶点数据
 31     EdgeNode *firstEdge;    //指向第一条依附该顶点的边的指针
 32 }VexNode, AdjList[MAX_NUM];
 33 
 34 typedef struct
 35 {
 36     AdjList adjList;
 37     int vexNum, edgeNum;    //顶点数和边数
 38 }ALGraph;
 39 
 40 /*
 41  * 队列存储结构(用于图的遍历)
 42  */
 43 typedef struct QNode
 44 {
 45     QElemType data;    //结点数据
 46     struct QNode *next;    //指向下一个结点
 47 }QNode, *QueuePtr;
 48 
 49 typedef struct
 50 {
 51     QueuePtr front;    //队头指针
 52     QueuePtr rear;    //队尾指针
 53 }LinkQueue;
 54 
 55 /*
 56  * 初始化队列
 57  */
 58 Status InitQueue(LinkQueue *Q)
 59 {
 60     Q->front = Q->rear = (QueuePtr) malloc(sizeof(QNode));
 61     if (!Q->front)
 62     {
 63         exit(OVERFLOW);
 64     }
 65     Q->front->next = NULL;
 66     return OK;
 67 }
 68 
 69 /*
 70  * 判断队列是否为空
 71  */
 72 Status IsEmpty(LinkQueue Q)
 73 {
 74     if (Q.front->next == NULL)
 75     {
 76         return TRUE;
 77     }
 78     else
 79     {
 80         return FALSE;
 81     }
 82 }
 83 
 84 /*
 85  * 入队
 86  */
 87 Status EnQueue(LinkQueue *Q, QElemType e)
 88 {
 89     QueuePtr p = (QueuePtr) malloc(sizeof(QNode));
 90     if (!p)
 91     {
 92         exit(OVERFLOW);
 93     }
 94     p->data = e;
 95     p->next = NULL;
 96     Q->rear->next = p;
 97     Q->rear = p;
 98     return OK;
 99 }
100 
101 /*
102  * 出队
103  */
104 Status DeQueue(LinkQueue *Q, QElemType *e)
105 {
106     QueuePtr p;
107     if (Q->front == Q->rear)
108     {
109         return ERROR;
110     }
111     p = Q->front->next;
112     *e = p->data;
113     Q->front->next = p->next;
114     if (Q->rear == p)
115     {
116         Q->rear = Q->front;
117     }
118     free(p);
119     return OK;
120 }
121 
122 /*
123  * 创建图
124  */
125 Status CreateGraph(ALGraph *G)
126 {
127     int i, j, k;
128     EdgeLink e;
129     printf("请输入顶点数目和边数:\n");
130     scanf("%d", &G->vexNum);
131     scanf("%d", &G->edgeNum);
132     getchar();
133     printf("请输入各顶点的数据:\n");
134     for (i = 0; i < G->vexNum; i++)
135     {
136         scanf("%c",&G->adjList[i].data);
137         if (G->adjList[i].data == '\n')
138         {
139             i--;
140             continue;
141         }
142         G->adjList[i].firstEdge = NULL;
143     }
144 
145     printf("请依次输入边(Vi,Vj)的顶点序号:\n");
146     for (k = 0; k < G->edgeNum; k++)
147     {
148         scanf("%d", &i);
149         scanf("%d", &j);
150         e = (EdgeLink) malloc(sizeof(EdgeNode));
151         e->adjvex = j;
152         e->next = G->adjList[i].firstEdge;
153         G->adjList[i].firstEdge = e;
154         e = (EdgeLink) malloc(sizeof(EdgeNode));
155         e->adjvex = i;
156         e->next = G->adjList[j].firstEdge;
157         G->adjList[j].firstEdge = e;
158     }
159     return OK;
160 }
161 
162 int visited[MAX_NUM];    //用于记录遍历状态
163 
164 /*
165  * 递归从第i个结点深度优先遍历图
166  */
167 void DFS(ALGraph G, int i)
168 {
169     EdgeLink p;
170     visited[i] = TRUE;
171     printf("%c ", G.adjList[i].data);
172     p = G.adjList[i].firstEdge;
173     while (p)
174     {
175         if (!visited[p->adjvex])
176         {
177             DFS(G, p->adjvex);
178         }
179         p = p->next;
180     }
181 }
182 
183 /*
184  * 深度优先遍历
185  */
186 Status DFSTraverse(ALGraph G)
187 {
188     int i;
189     for (i = 0; i < MAX_NUM; i++)
190     {
191         visited[i] = FALSE;
192     }
193     for (i = 0; i < G.vexNum; i++)
194     {
195         if (!visited[i])
196         {
197             DFS(G, i);
198         }
199     }
200     return OK;
201 }
202 
203 /*
204  * 广度优先遍历
205  */
206 Status BFSTraverse(ALGraph G)
207 {
208     int i;
209     EdgeLink p;
210     LinkQueue Q;
211     InitQueue(&Q);
212     for (i = 0; i < MAX_NUM; i++)
213     {
214         visited[i] = FALSE;
215     }
216     for (i = 0; i < G.vexNum; i++)
217     {
218         if (!visited[i])
219         {
220             visited[i] = TRUE;
221             printf("%c ", G.adjList[i].data);
222             EnQueue(&Q, i);
223             while (!IsEmpty(Q))
224             {
225                 DeQueue(&Q, &i);
226                 p = G.adjList[i].firstEdge;
227                 while (p)
228                 {
229                     if (!visited[p->adjvex])
230                     {
231                         visited[p->adjvex] = TRUE;
232                         printf("%c ", G.adjList[p->adjvex].data);
233                         EnQueue(&Q, p->adjvex);
234                     }
235                     p = p->next;
236                 }
237             }
238         }
239     }
240     return OK;
241 }
242 
243 int main()
244 {
245     ALGraph G;
246     CreateGraph(&G);
247     printf("深度优先遍历:");
248     DFSTraverse(G);
249     printf("\n广度优先遍历:");
250     BFSTraverse(G);
251     printf("\n");
252 }

转载于:https://www.cnblogs.com/niceforbear/p/4529470.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值