热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

数据结构之图的深度优先搜索

数据结构之图的深度优先搜索,Go语言社区,Golang程序员人脉社

下面来讲一下图的深度优先搜索的方法。

遍历原则

从图中某一个指定的顶点v出发,先访问v,然后从该顶点未被访问过的邻接顶点w出发进行深度优先搜索,直到图中与v想通的所有顶点都被访问,此时相当于完成图中一个包含顶点v的连通分量的遍历。如果图中存在尚未遍历过的顶点,则从另一个未被访问的顶点出发重复上述过程,直到图中所有顶点均被遍历到。

显然,深度优先搜索算法是一种递归算法

分析:

假设有一幅图,如下图所示。


该图的邻接表为:


如果对该图进行深度优先搜索,步骤如下:

STEP1:从顶点A出发进行深度优先搜索。首先访问顶点A,并将A标注为已访问状态(图中标注为黄色),然后去找顶点A的第一个邻接点,如果第一个邻接点已被访问,则搜索顶点A的下一个邻接点。显然,顶点A的第一个邻接点为顶点B,且B未被访问。

STEP2:访问顶点B,并将B标注为已访问状态(图中标注为绿色),然后寻找顶点B的第一个邻接点,该邻接点为A,但是由于顶点A已经被访问过,因此继续寻找顶点B的下一个邻接点C,发现顶点C未被访问过。


STEP3:访问顶点C,并将C标注为已访问状态(图中标注为橙色),寻找C的第一个邻接点B,因为B已经被访问,因此寻找下一个邻接点D,D未被访问过。


STEP4:访问顶点D,并将D标注为已访问状态(图中标注为蓝色),寻找D的第一个邻接点A,A已经被访问过,不断寻找D的下一个邻接点,知道找到第一个未被访问的顶点E。


STEP5:访问顶点E,并将E标注为已访问状态(图中标注为红色),访问E的第一个邻接点D,发现D已经被访问过,然后去找E的下一个邻接点,发现没有邻接点,则返回上一层,也就是STEP4。


STEP6:寻找顶点D的下一个未被访问的邻接点F,访问顶点F,并将F标注为已访问状态(图中标注为紫色)。寻找F的第一个邻接点D,发现D已经被访问过,寻找F的下一个邻接点,发现没有邻接点,则返回上一层,也就是STEP4。


STEP7:寻找顶点D的未被访问的邻接点,发现不存在这样的邻接点,则返回STEP3层;寻找顶点C的未被访问的邻接点,发现不存在这样的邻接点,则返回STEP2层;寻找顶点B的未被访问的邻接点,发现不存在这样的邻接点,则返回STEP1层;寻找顶点A的未被访问的邻接点,发现不存在这样的邻接点,则退出程序。此时,图中各个顶点的访问便结束了。

代码:

1.定义图的顶点结构体VLink以及边的结构体ELink,并设置一个数组visited,该数组用来标记顶点是否被访问。例如:若visited[0]=0,说明下标为0的顶点未被访问,若visited[3]=1,说明下标为3的顶点被访问了。

#define MAXNUM 100
int visited[MAXNUM];

typedef struct edge {
	int adjvex;
	edge* next;
}ELink;

typedef struct ver {
	char vertex;
	ELink* link;
}VLink;

2.定义深度优先搜索的主算法。

void TRAVER_DFS(VLink G[], int vSize, int visited[]) {
	//初始化访问数组
	for(int i=0; i

3.定义深度优先搜索DFS算法。

void DFS( VLink G[], int v ) {
	int w;
	cout <


4.定义寻找顶点v的第一个邻接点的函数FirstADJ

int FirstADJ( VLink G[], int v ) {
	ELink *p = G[v].link;
	if(p) {
		return p->adjvex;
	}
	else {
		return -1;
	}
}
5.定义寻找顶点v的下一个未被访问的邻接点的函数NextADJ

int NextADJ( VLink G[], int v ) {
	ELink *p = G[v].link;
	while(p) {
		if(visited[p->adjvex] == 0) {
			return p->adjvex;
		}
		p = p->next;
	}
	return -1;
}

6.定义打印图的邻接表的函数

void printADJLIST(VLink G[], int vSize) {
	ELink *p;
	for(int i=0; i" <adjvex;
			p = p->next;
		}
		cout <

7.定义主函数

int _tmain(int argc, _TCHAR* argv[])
{
	VLink vArray[6];
	for(int i=0; i<6; i++) {
		vArray[i].vertex = 'A' + i;
		vArray[i].link = NULL;
	}
	ELink* edge1 = new ELink;
	ELink* edge2 = new ELink;
	ELink* edge3 = new ELink;
	ELink* edge4 = new ELink;
	ELink* edge5 = new ELink;
	ELink* edge6 = new ELink;
	ELink* edge7 = new ELink;
	ELink* edge8 = new ELink;
	ELink* edge9 = new ELink;
	ELink* edge10 = new ELink;
	ELink* edge11 = new ELink;
	ELink* edge12 = new ELink;
	edge1->adjvex = 1; edge1->next = edge2;
	edge2->adjvex = 3; edge2->next = NULL;
	edge3->adjvex = 0; edge3->next = edge4;
	edge4->adjvex = 2; edge4->next = NULL;
	edge5->adjvex = 1; edge5->next = edge6;
	edge6->adjvex = 3; edge6->next = NULL;
	edge7->adjvex = 0; edge7->next = edge8;
	edge8->adjvex = 2; edge8->next = edge9;
	edge9->adjvex = 4; edge9->next = edge10;
	edge10->adjvex = 5; edge10->next = NULL;
	edge11->adjvex = 3; edge11->next = NULL;
	edge12->adjvex = 3; edge12->next = NULL;
	vArray[0].link = edge1;
	vArray[1].link = edge3;
	vArray[2].link = edge5;
	vArray[3].link = edge7;
	vArray[4].link = edge11;
	vArray[5].link = edge12;

	printADJLIST(vArray, 6);
	TRAVER_DFS(vArray, 6, visited);

	delete edge1;
	delete edge2;
	delete edge3;
	delete edge4;
	delete edge5;
	delete edge6;
	delete edge7;
	delete edge8;
	delete edge9;
	delete edge10;
	delete edge11;
	delete edge12;
	return 0;
}

输出结果如下:



推荐阅读
  • PHP函数的工作原理与性能分析
    在编程语言中,函数是最基本的组成单元。本文将探讨PHP函数的特点、调用机制以及性能表现,并通过实际测试给出优化建议。 ... [详细]
  • 本文将深入探讨 Unreal Engine 4 (UE4) 中的距离场技术,包括其原理、实现细节以及在渲染中的应用。距离场技术在现代游戏引擎中用于提高光照和阴影的效果,尤其是在处理复杂几何形状时。文章将结合具体代码示例,帮助读者更好地理解和应用这一技术。 ... [详细]
  • 本文详细探讨了select和epoll两种I/O多路复用技术的内部实现原理,分析了它们在处理大量文件描述符时的性能差异,并通过具体示例代码展示了select的工作流程。 ... [详细]
  • 本文回顾了作者在求职阿里和腾讯实习生过程中,从最初的迷茫到最后成功获得Offer的心路历程。文中不仅分享了个人的面试经历,还提供了宝贵的面试准备建议和技巧。 ... [详细]
  • 使用Matlab创建动态GIF动画
    动态GIF图可以有效增强数据表达的直观性和吸引力。本文将详细介绍如何利用Matlab软件生成动态GIF图,涵盖基本代码实现与高级应用技巧。 ... [详细]
  • 本文探讨了如何在PHP与MySQL环境中实现高效的分页查询,包括基本的分页实现、性能优化技巧以及高级的分页策略。 ... [详细]
  • MySQL InnoDB 存储引擎索引机制详解
    本文深入探讨了MySQL InnoDB存储引擎中的索引技术,包括索引的基本概念、数据结构与算法、B+树的特性及其在数据库中的应用,以及索引优化策略。 ... [详细]
  • 深入探讨前端代码优化策略
    本文深入讨论了前端开发中代码优化的关键技术,包括JavaScript、HTML和CSS的优化方法,旨在提升网页加载速度和用户体验。 ... [详细]
  • 在Effective Java第三版中,建议在方法返回类型中优先考虑使用Collection而非Stream,以提高代码的灵活性和兼容性。 ... [详细]
  • 本文探讨了如何利用Unicode编码及汉字拼音来实现数组内姓名的高效排序。具体而言,首先根据首字母的Unicode值对数字、字母进行排序,接着对中文姓名依据其拼音首字母进行排序。 ... [详细]
  • 本文探讨了在已知最终数组尺寸不会超过5000x10的情况下,如何利用预分配和调整大小的方法来优化Numpy数组的创建过程,以提高性能并减少内存消耗。 ... [详细]
  • LeetCode 102 - 二叉树层次遍历详解
    本文详细解析了LeetCode第102题——二叉树的层次遍历问题,提供了C++语言的实现代码,并对算法的核心思想和具体步骤进行了深入讲解。 ... [详细]
  • 深入解析 C++ 中的 String 和 Vector
    本文详细介绍了 C++ 编程语言中 String 和 Vector 的使用方法及特性,旨在帮助开发者更好地理解和应用这两个重要的容器。 ... [详细]
  • 想把一组chara[4096]的数组拷贝到shortb[6][256]中,尝试过用循环移位的方式,还用中间变量shortc[2048]的方式。得出的结论:1.移位方式效率最低2. ... [详细]
  • 本文深入探讨了Linux内核中进程地址空间的设计与实现,包括虚拟地址空间的概念、内存描述符`mm_struct`的作用、内核线程与用户进程的区别、进程地址空间的分配方法、虚拟内存区域(VMA)的结构以及地址空间与页表之间的映射机制。 ... [详细]
author-avatar
ht遨游遐想
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有