热门标签 | 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;
}

输出结果如下:



推荐阅读
  • 2023年京东Android面试真题解析与经验分享
    本文由一位拥有6年Android开发经验的工程师撰写,详细解析了京东面试中常见的技术问题。涵盖引用传递、Handler机制、ListView优化、多线程控制及ANR处理等核心知识点。 ... [详细]
  • 优化ListView性能
    本文深入探讨了如何通过多种技术手段优化ListView的性能,包括视图复用、ViewHolder模式、分批加载数据、图片优化及内存管理等。这些方法能够显著提升应用的响应速度和用户体验。 ... [详细]
  • 本文详细介绍了 GWT 中 PopupPanel 类的 onKeyDownPreview 方法,提供了多个代码示例及应用场景,帮助开发者更好地理解和使用该方法。 ... [详细]
  • 1:有如下一段程序:packagea.b.c;publicclassTest{privatestaticinti0;publicintgetNext(){return ... [详细]
  • 1.如何在运行状态查看源代码?查看函数的源代码,我们通常会使用IDE来完成。比如在PyCharm中,你可以Ctrl+鼠标点击进入函数的源代码。那如果没有IDE呢?当我们想使用一个函 ... [详细]
  • 题目描述:给定n个半开区间[a, b),要求使用两个互不重叠的记录器,求最多可以记录多少个区间。解决方案采用贪心算法,通过排序和遍历实现最优解。 ... [详细]
  • 深入理解C++中的KMP算法:高效字符串匹配的利器
    本文详细介绍C++中实现KMP算法的方法,探讨其在字符串匹配问题上的优势。通过对比暴力匹配(BF)算法,展示KMP算法如何利用前缀表优化匹配过程,显著提升效率。 ... [详细]
  • 本文详细介绍了Java编程语言中的核心概念和常见面试问题,包括集合类、数据结构、线程处理、Java虚拟机(JVM)、HTTP协议以及Git操作等方面的内容。通过深入分析每个主题,帮助读者更好地理解Java的关键特性和最佳实践。 ... [详细]
  • 360SRC安全应急响应:从漏洞提交到修复的全过程
    本文详细介绍了360SRC平台处理一起关键安全事件的过程,涵盖从漏洞提交、验证、排查到最终修复的各个环节。通过这一案例,展示了360在安全应急响应方面的专业能力和严谨态度。 ... [详细]
  • 本章将深入探讨移动 UI 设计的核心原则,帮助开发者构建简洁、高效且用户友好的界面。通过学习设计规则和用户体验优化技巧,您将能够创建出既美观又实用的移动应用。 ... [详细]
  • 利用存储过程构建年度日历表的详细指南
    本文将介绍如何使用SQL存储过程创建一个完整的年度日历表。通过实例演示,帮助读者掌握存储过程的应用技巧,并提供详细的代码解析和执行步骤。 ... [详细]
  • 本文深入探讨了C++对象模型中的一些细节问题,特别是虚拟继承和析构函数的处理。通过具体代码示例和详细分析,揭示了书中某些观点的不足之处,并提供了更合理的解释。 ... [详细]
  • Codeforces Round #566 (Div. 2) A~F个人题解
    Dashboard-CodeforcesRound#566(Div.2)-CodeforcesA.FillingShapes题意:给你一个的表格,你 ... [详细]
  • 本文深入探讨了二叉搜索树(Binary Search Tree, BST)及其操作,包括查找、插入和删除节点。同时,文章还介绍了平衡二叉树(AVL树)的概念及调整方法,并详细讨论了如何判断两个序列是否构成相同的二叉搜索树。 ... [详细]
  • 使用Vultr云服务器和Namesilo域名搭建个人网站
    本文详细介绍了如何通过Vultr云服务器和Namesilo域名搭建一个功能齐全的个人网站,包括购买、配置服务器以及绑定域名的具体步骤。文章还提供了详细的命令行操作指南,帮助读者顺利完成建站过程。 ... [详细]
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社区 版权所有