数据结构的图论算法(二)——图的遍历

总:图的两种遍历方式:

1.深度优先遍历(DFS,Depth First Search)

2.广度优先遍历(BFS,Breadth First Search)

(这里的遍历方式主要是针对以邻接表为存储形式的)
  • 从定义出发:

图的遍历:从图中某一顶点出发访遍图中其余顶点,且使每一个顶点仅被访问一次

因此,为防止一个顶点被访问多次,设一个辅助数组visited[n];

visited[i] = 0或FALSE		//vi未被访问过
visited[i] = 1或TRUE		//vi已被访问
遍历方式:深度优先遍历广度优先遍历
特点:类似于树的先根遍历类似于树的层次遍历

具体遍历方式如下:

—深度优先遍历(DFS)

  1. 从图中某顶点v出发,访问该顶点;
  2. 依次从v的未被访问的邻接点出发继续对图进行深度优先遍历直至图中所有和v有路径相通的顶点都被访问到
  3. 若图中仍有顶点未被访问, 则另选一个未曾被访问的顶点作起始点,重复上述过程,直到图中所有顶点都被访问为止

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
算法如下:(邻接表的组成结构参考上一篇图的定义结构中的邻接表组成)

//图的邻接表表示:
typedef struct adjVert{		//边
	int adjvert;	//存储邻接顶点的地址
	int edgeInfo;
	struct adjVert *next;
}Graph_AdjVert;

typedef struct vert{	//顶点
	char data[128];
	adjVert *firstarc;
}Graph_Vert;

typedef struct{		//图
	Graph_Vert v[MAX_VERTEX_NUM];
	int n;
}Graph;
Boolean visited[MAX_VERTEX_NUM];	//顶点访问标志的数组

void DFSTraverse(ALGraph G){
	int i;
	//初始化:
	for(i = 0; i < G.n; ++i)visited[i] = FALSE;
	//开始对顶点表进行查阅,看是否都已经遍历了,如果有顶点没有访问过,就顺着该顶点进行深度遍历
	for(i = 0; i < G.n; ++i)	//如果结点没有被访问
		if(!visited[i]) DFS(G,i);
}

void DFS(ALGraph G, int i){		//顺着某一个顶点进行深度遍历
	//先访问该顶点
	visited[i] = TRUE;
	ArcNode *p = G.v[i].firstarc;//让p指向第一个邻接顶点;
	while(p){		//如果p存在,即存在邻接顶点而不是NULL,就表示可以遍历
		if(!visited[p->adjvex])//如果该点没有被访问过,就递归深度遍历
			DFS(G, p->adjvex);
		p = p->nextarc;	//若没有执行if语句,也就是已经被访问过,就将p指向下一个邻接顶点;
	}
}

—广度优先遍历(BFS)

  1. 从图中某顶点v出发,访问该顶点,并依次访问V0的各个未曾访问过的邻接点;
  2. 然后分别从这些邻接点出发直至图中所有已被访问的顶点的邻接点都被访问到
  3. 若图中仍有顶点未被访问, 则另选一个未曾被访问的顶点作起始点,重复上述过程,直到图中所有顶点都被访问为止。

在这里插入图片描述
广度遍历后:在这里插入图片描述

遍历顺序:
V1,V2,V3,V4,V5,V6,V7,V8

算法实现如下:


//前期的队列准备

//创建辅助队列的结构
typedef struct SQueue{
	int v[MAX_VERTEX_NUM];
	int front,rear;
}SQueue;

//队列初始化
void InitQueue(SQueue *q){
	q->front = q->rear = 0;
}

//元素入队
void EnQueue(SQueue *q, int elmt){
	q->v[q->rear] = elmt;
	q->rear = (q->rear+1)%MAX_VERTEX_NUM;
}

//判断队列是否为空
int QueueEmpty(SQueue *q){
	return (q->rear - q->front <= 0);
}

//元素出队
int DeQueue(SQueue *q){
	int elmt;
	if(!QueueEmpty(q)){
		elmt = q->v[q->front];  
		q->front = (q->front+1) % MAX_VERTEX_NUM;
    }
	return elmt;
}


//广度优先遍历:
void BFS(Graph G){
	int i;
	//创建辅助队列
	SQueue *Q;
	Q = (SQueue *)malloc(sizeof(SQueue));
	//初始化
	for(i = 0 ; i < G.n; i++)	visited[i] = FALSE;
	InitQueue(Q);
	
	for(i = 0; i < G.n; i++){
		if(!visited[i]){	//若未被访问
			visited[i] = TRUE;
			EnQueue(Q, i);	//将该点入队
			
			while(!QueueEmpty(Q)){
				i = DeQueue(Q);	//队头元素出队并存在e中;
				Graph_AdjVert *p = G.v[i].firstarc;
				while(p){
					if(!visited[p->adjvert]){
						p->adjvert = TRUE;
						EnQueue(Q,p->adjvert);
					}
					p = p->next;
				}
			}
		}
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值