数据结构 第七章(学习笔记三(图的遍历))

图的遍历

从图中某一顶点出发,按照某种搜索方法沿着图中的边对图中的所有顶点访问一次且仅访问一次。

图的遍历之深度优先探索

深度优先探索

深度优先搜索(DepthFirstSearch) ,也有称为深度优先遍历,简称为DFS

拿找钥匙例子来说, 无论从哪一间房间开始都可以,将房间内的墙角 、床头柜、床上、床下、衣柜、电视柜等挨个寻找,做到不放过任何一个死角,当所有的抽屉、 储藏柜等全部都找遍,接着再寻找下一个房间。

具体实现思路

首先访问起始顶点v;
接着由v出发访问v的任意一个 邻接且未被访问 的邻接顶点Wi;
然后再访问与Wi 邻接且未被访问 的任意顶点 yi;
若w没有邻接且未被访问的顶点时, 退回到它的上一层顶点v;
重复上述过程,直到所有顶点被访问为止。

实例

遵循右手原则遍历,蓝色线为走的线。

参考代码实现

bool visited[MAX_TREE_SIZE];
void DFSTraverse(Graph G){
    for(int i = 0; i < G.vexnum; i++)
        visited[i] = FALSE;
    for(int i = 0; i < G.vexnum; i++)
        if(!visited[i])
            DFS(G, i);
}
void DFS (Graph G, int v){
    visit(v);
    visited[v] = TRUE;
    for(w = FirstNeighbor(G, v); w >= 0; w = NextNeighbor(G, v, w))
    	if(!visited[i])        i
            DFS(G, w);
}

图的遍历之广度优先探索

广度优先探索

广度优先搜索(BreadthFirstSearch),又称为广度优先遍历,简称 BFS

我们还用找钥匙的例子来讲,运用深度优先遍历意味着要先彻底查找完一个房间再开始另一个房间,但我们知道,钥匙放在沙发地下等特殊角落的可能性极低,因此我们运用新的方亲:先看看钥匙是否放在各个房间的明显位置,如果没有,再看看各个房间的抽屉有没有。这样逐步扩大查找的范围的方式我们称为广度优先搜索 。

具体实现思路

首先访问起始顶点v;
接着由出发依次访问v的各个 未被访问过 的邻接顶点W1, W2….Wi;
然后依次访问W1, W2…,Wi 的所有 未被访问过 的邻接顶点;
在从这些访问过的顶点出发,访问它们所有 未被访问过的 邻接顶点;
以此类推……;

实例


参考代码实现

//邻接表的广度优先搜索
bool visited[MAX_TRUE_SIZE];		//辅助标记数组
void BFSTraverse(Mgraph G){
    int i, j;
    Queue Q;		
    for( i = 0; i < G.vexnum; i++)		//将辅助标记数组全部初始化为FALSE, G.vexnum表示顶点数
    {
        visited[i] = FALSE;
    }
    initQueue( &Q);		//初始化队列
    for( i = 0; i < G.vexnum; i++){
        if(!visited[i])	{
            printf("%c  ", G.vetices[i].data);	//访问顶点
            visited[i] = TRUE;
            EnQueue(&Q, i);
            while(!QueueEmpty(Q)){
                DeQueue(&Q, i);
                ArcNode P = G.AdjList[i].first;
                while(p != NULL && !visited[i])		// 单链表指针为非NULL 且 未被访问
                {
                    printf("%c  ", G.vetices[p.adjvex].data);	//访问顶点
                    visited[j] = TRUE;
                    EnQueue(&Q, j);
                }
            }    
        }
    }
}

DFS&BFS实现图的遍历完整代码

#include<stdio.h>

#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0

typedef int Status;
typedef int Boolean;

typedef char VertexType;//顶点类型
typedef int EdgeType;//边的权值类型

#define MAXSIZE 9
#define MAXEDGE 15
#define MAXVEX 9
#define INFINTY 65535

typedef struct {
	VertexType vexs[MAXVEX];
	EdgeType arc[MAXVEX][MAXVEX];
	int numVertexes, numEdges;
}MGraph;

typedef struct {
	int data[MAXSIZE];
	int front;
	int rear;
}Queue;

Status InitQueue(Queue* Q){
	Q->front = 0;
	Q->rear = 0;
	return  OK;
}

/* 若队列Q为空队列,则返回TRUE,否则返回FALSE */
Status QueueEmpty(Queue Q){
	if (Q.front == Q.rear)
		return TRUE;
	else
		return FALSE;
}

/* 若队列未满,则插入元素e为Q新的队尾元素 */
Status EnQueue(Queue* Q, int e){
	if ((Q->rear + 1) % MAXSIZE == Q->front)
		return ERROR;
	Q->data[Q->rear] = e;
	Q->rear = (Q->rear + 1) % MAXSIZE;
	return  OK;
}

/* 若队列不空,则删除Q中队头元素,用e返回其值 */
Status DeQueue(Queue* Q, int* e){
	if (Q->front == Q->rear)
		return ERROR;
	*e = Q->data[Q->front];	
	Q->front = (Q->front + 1) % MAXSIZE;
	return  OK;
}

void CreateMGraph(MGraph* G){
	int i, j;
	G->numEdges = 9;
	G->numVertexes = 8;
	G->vexs[0] = 'A';
	G->vexs[1] = 'B';
	G->vexs[2] = 'C';
	G->vexs[3] = 'D';
	G->vexs[4] = 'E';
	G->vexs[5] = 'F';
	G->vexs[6] = 'G';
	G->vexs[7] = 'H';

	for (i = 0; i < G->numVertexes; i++){
		for (j = 0; j < G->numVertexes; j++){
			G->arc[i][j] = 0;
		}
	}

	G->arc[0][1] = 1;
	G->arc[0][2] = 1;

	G->arc[1][3] = 1;
	G->arc[1][4] = 1;

	G->arc[2][5] = 1;
	G->arc[2][6] = 1;

	G->arc[3][7] = 1;

	G->arc[4][7] = 1;

	G->arc[5][6] = 1;

	for (i = 0; i < G->numVertexes; i++){
		for (j = i; j < G->numVertexes; j++){
			G->arc[j][i] = G->arc[i][j];
		}
	}
}

Boolean visited[MAXVEX]; /* 访问标志的数组 */

/* 邻接矩阵的深度优先递归算法 */
void DFS(MGraph G, int i){
	int j;
	visited[i] = TRUE;
	printf("%c ", G.vexs[i]);
	for (j = 0; j < G.numVertexes; j++)
		if (G.arc[i][j] == 1 && !visited[j])
			DFS(G, j);
}

/* 邻接矩阵的深度遍历操作 */
void DFSTraverse(MGraph G){
	int i;
	for (i = 0; i < G.numVertexes; i++)
		visited[i] = FALSE;
	for (i = 0; i < G.numVertexes; i++)
		if (!visited[i])
			DFS(G, i);
}

/* 邻接矩阵的广度遍历算法 */
void BFSTraverse(MGraph G){
	int i, j;
	Queue Q;
	for (i = 0; i < G.numVertexes; i++)
		visited[i] = FALSE;
	InitQueue(&Q);
	for (i = 0; i < G.numVertexes; i++){
		if (!visited[i]){
			visited[i] = TRUE;
			printf("%c ", G.vexs[i]);
			EnQueue(&Q, i);
			while (!QueueEmpty(Q)){
				DeQueue(&Q, &i);
				for (j = 0; j < G.numVertexes; j++){
					if (G.arc[i][j] == 1 && !visited[j]){
						visited[j] = TRUE;
						printf("%c ", G.vexs[j]);
						EnQueue(&Q, j);
					}
				}
			}
		}
	}
}

int main(){
	MGraph G;
	CreateMGraph(&G);
	printf("\n深度遍历:");
	DFSTraverse(G);
	printf("\n广度遍历:");
	BFSTraverse(G);

	return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值