树的遍历-深度优先遍历和广度优先遍历

2023-11-06

深度优先遍历类似于树的先序遍历。假设给定初态是图中所有顶点均未被访问过,从图中某一顶点vi出发遍历图中的定义如下:首先访问出发点vi,并将其访问标志置为1;然后,从vi出发点依次搜索vi的每个邻接点vj。如vj未被访问过,则以vj为新的出发点继续进行深度优先搜索。

广度优先遍历,类似于树的按层次遍历。设图G是连通的,且图G的初态是所有顶点均未被访问过。从图G的任一顶点vi出发按广度优先搜索遍历图的步骤是:访问vi后,依次访问与vi邻接的所有顶点w1,w2,w3......wn,再按w1,w2,w3......wn的顺序访问其中每个顶点的所有未被访问的邻接点,再按此顺序,依次访问它们所有未被访问的邻接点,以此类推,直到图中所有顶点均被访问过为止。

比如,以下面的图为例(包括不连通的顶点):


图中包括9个顶点,顶点序号为0~8,顶点信息为依次为字符 'a' ~ ' i',其中顶点8不与其他顶点相连通。

利用递归形式的深度优先遍历:

遍历结果:0->1->3->7->4->5->2->6 ->8         输出结果:a->b->d->h->e->f->c->g->i

利用非递归形式(栈)的深度优先遍历:

遍历结果:0->1->3->7->4->5->2->6 ->8         输出结果:a->b->d->h->e->f->c->g->i

利用广度优先遍历(队列):

遍历结果:0->1->2->3->4->5->6->7 ->8         输出结果:a->b->c->d->e->f->g->h->i


程序如下(有问题共同交流):

#include<iostream>
#include<assert.h>
#include<string>

#define NUM 9
#define MAXSIZE 15
using namespace std;

typedef struct graph
{
	char vertexs[NUM];
	int matrixs[NUM][NUM];
};

typedef struct stack
{
	int dataNum[MAXSIZE];
	int top;
	int stackSize;
};

typedef struct queue
{
	int dataArray[MAXSIZE];
	int front;
	int rear;
};

//直接创建图
void CreateGraph(graph * g);
//深度优先遍历(递归形式)图中所有连通顶点,打印顶点信息
void DFS(graph* g, int i, int visit[NUM]);
//深度优先遍历(递归形式)图中剩余其他顶点,打印顶点信息
void FinalDFS(graph* g, int visit[NUM]);

//创建栈
void CreateStack(stack *s);
//判断栈是否为空
int EmptyStack(stack *s);
//将顶点序号入栈
void PushStack(stack *s, int k);
//出栈,取栈顶元素
int PopStack(stack *s);
//利用栈,深度优先遍历(非递归形式)图中每个顶点
void DFS_Stack(graph *g, int i, stack* s, int visit[NUM]);
//利用栈,深度优先遍历(非递归形式)图中所有顶点
void FinalDFS_Stack(graph *g, stack* s, int visit[NUM]);

//创建队列
void CreateQueue(queue *q);
//判断队列是否为空
int EmptyQueue(queue *q);
//入队,将顶点序号入队
void ENQUEUE(queue *q, int e);
//出队,将队头元素出队
int DEQUEUE(queue *q);
//利用队列,广度优先遍历图中和源点i相连通的所有顶点
void BFS_Queue(graph *g, int i, queue* q, int visit[NUM]);
//利用队列,广度优先遍历图中所有顶点(包括不连通顶点)
void FinalBFS_Queue(graph *g, queue* q, int visit[NUM]);


int main()
{
	graph g;
	CreateGraph(&g);
	int visit[NUM] = {0};

	//利用深度优先搜索遍历(递归形式)
	printf("深度优先遍历(递归形式): ");
	FinalDFS(&g,visit);
	printf("\n");

	//利用深度优先遍历(非递归形式:栈)
	printf("深度优先遍历(非递归形式 栈): ");
	int visit1[NUM] = { 0 };
	stack s;
	CreateStack(&s);
	FinalDFS_Stack(&g, &s, visit1);
	printf("\n");

	//利用广度优先遍历(队列)
	printf("广度优先遍历(队列): ");
	int visit2[NUM] = { 0 };
	queue q;
	CreateQueue(&q);
	FinalBFS_Queue(&g, &q, visit2);
	printf("\n");

	return 0;
}

//创建图
void CreateGraph(struct graph * g)
{
	//默认9个顶点信息依次为字符"a b c d e f g h i"
	for (int i = 0; i < NUM; i++)
	{
		g->vertexs[i] = 'a'+i;
	}

	//直接创建图的邻接矩阵
	g->matrixs[0][1] = 1;
	g->matrixs[0][2] = 1;

	g->matrixs[1][0] = 1;
	g->matrixs[1][3] = 1;
	g->matrixs[1][4] = 1;

	g->matrixs[2][0] = 1;
	g->matrixs[2][5] = 1;
	g->matrixs[2][6] = 1;

	g->matrixs[3][1] = 1;
	g->matrixs[3][7] = 1;

	g->matrixs[4][1] = 1;
	g->matrixs[4][7] = 1;

	g->matrixs[5][2] = 1;
	g->matrixs[5][7] = 1;

	g->matrixs[6][2] = 1;
	g->matrixs[6][7] = 1;

	g->matrixs[7][3] = 1;
	g->matrixs[7][4] = 1;
	g->matrixs[7][5] = 1;
	g->matrixs[7][6] = 1;
}


//深度优先遍历(递归形式)图中所有联通顶点,打印顶点信息
void DFS(graph* g, int i, int visit[NUM])
{
	//将访问到的顶点的标志位赋1
	visit[i] = 1;
	//打印访问到的顶点信息
	printf("%c ", g->vertexs[i]);
	for (int j = 0; j < NUM; j++)
	{
		if (g->matrixs[i][j]==1 && visit[j]==0)
		{
			DFS(g,j,visit);
		}
	}
}

//深度优先遍历(递归形式)图中所有顶点,打印顶点信息
void FinalDFS(graph* g, int visit[NUM])
{

	//遍历所有顶点
	for (int m = 0; m < NUM; m++)
	{
		if (visit[m] == 0)
		{
			DFS(g, m, visit);
		}
	}
}

//创建栈
void CreateStack(stack *s)
{
	//将栈置空
	s->top = -1;
	s->stackSize = MAXSIZE;
}

//判断栈是否为空
int EmptyStack(stack *s)
{
	if (s->top==-1)  return 1;
    else return 0;
}

//将顶点序号入栈
void PushStack(stack *s, int k)
{
	if (s->top == (s->stackSize-1))
	{
		printf("overflow");
		return;
	}
	else
	{
		s->top++;
		s->dataNum[s->top] = k;
	}
}

//出栈,取栈顶元素
int PopStack(stack *s)
{
	if (EmptyStack(s)==1)
	{
		return -1;
	}
	else
	{
		int vexNum=s->dataNum[s->top];
		s->top--;
		return vexNum;
	}
}

//利用栈,深度优先遍历(非递归形式)图中每个顶点
void DFS_Stack(graph *g, int i, stack* s, int visit[NUM])
{
	visit[i] = 1;
	//将第一个顶点入栈
	PushStack(s,i);
	//打印第一个顶点信息
	printf("%c ",g->vertexs[s->dataNum[s->top]]);
	while (s->top!=-1)
	{
		int x = s->dataNum[s->top];
		int flag = 0;
		for (int j = 0; j < NUM;j++)
		{
			if (g->matrixs[x][j] == 1 && visit[j] == 0)
			{
				visit[j] = 1;
				PushStack(s,j);
				flag = 1;
				printf("%c ", g->vertexs[s->dataNum[s->top]]);
				break;
			}
		}	
		if (flag==0)
		{		
			PopStack(s);
		}  
	}
}

//利用栈,深度优先遍历(非递归形式)图中所有顶点
void FinalDFS_Stack(graph *g, stack* s, int visit[NUM])
{

	//遍历所有顶点
	for (int m = 0; m < NUM; m++)
	{
		if (visit[m] == 0)
		{
			DFS_Stack(g, m, s, visit);
		}
	}
}

//创建队列
void CreateQueue(queue *q)
{
	q->front = q->rear = 0;
}

//判断队列是否为空
int EmptyQueue(queue *q)
{
	if (q->front == q->rear) return 1;
	else return 0;
}

//入队,将顶点序号入队
void ENQUEUE(queue *q, int e)
{
	if (q->rear-q->front==(MAXSIZE-1))
	{
		printf("队满上溢");
		return;
	}
	else
	{
		q->dataArray[q->rear] = e;
		q->rear++;
	}
}

//出队,将队头元素出队
int DEQUEUE(queue *q)
{
	if (EmptyQueue(q)==1)
	{
		return -1;
	}
	else
	{
		int frontNum =q->dataArray[q->front];
		q->front++;
		return frontNum;
	}
}

//利用队列,广度优先遍历图中和源点i相连通的所有顶点
void BFS_Queue(graph *g, int i, queue* q, int visit[NUM])
{
	visit[i] = 1;
	//将第一个顶点入队
	ENQUEUE(q,i);
	//打印第一个顶点信息
	//printf("%c ", q->dataArray[q->front]);

	while (EmptyQueue(q)!=1)
	{
		int k = DEQUEUE(q);
		printf("%c ", g->vertexs[k]);
		for (int j = 0; j < NUM;j++)
		{
			if (g->matrixs[k][j] == 1 && visit[j] == 0)
			{
				visit[j] = 1;
				ENQUEUE(q, j);
			}
		}
	}
}

//利用队列,广度优先遍历图中所有顶点(包括不连通顶点)
void FinalBFS_Queue(graph *g, queue* q, int visit[NUM])
{
	//遍历所有顶点
	for (int m = 0; m < NUM; m++)
	{
		if (visit[m] == 0)
		{
			BFS_Queue(g, m, q, visit);
		}
	}
}

输出结果如下:


本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

树的遍历-深度优先遍历和广度优先遍历 的相关文章

  • C语言/C++实现栈操作

    一 栈的概念 栈是一种常用的数据结构 它遵循先入后出 Last In First Out LIFO 的原则 栈的操作只在栈的一端进行 该端被称为栈顶 而另一端称为栈底 栈的基本操作包括压栈 入栈 push 和弹栈 出栈 pop 分别用于将元
  • 以OpenGL/ES视角介绍gfx-hal(Vulkan) Shader/Program接口使用

    文档列表见 Rust 移动端跨平台复杂图形渲染项目开发系列总结 目录 背景 The right way to tackle this in Vulkan is to use resource descriptors A descriptor
  • Mysql 数据库

    数据库基础 1 什么是数据库 用来存储数据 数据库可在硬盘及内存中存储数据 数据库与文件存储数据的区别 数据库本质也是通过文件来存储数据 数据库的概念就是系统的管理存储数据的文件 数据库介绍 本质就是存储数据的C S架构的socket套接字
  • netty handler的执行顺序(3)

    2019独角兽企业重金招聘Python工程师标准 gt gt gt 今天解决2个问题 1 handler在pipeline当中究竟是如何存储的 2 在遍历handler的过程中 会根据event的不同 调用不同的handler 这一点是如何
  • 算法--将数组分成和相等的多个子数组,求子数组的最大个数

    作者 陈太汉 一个整数数组 长度为n 将其分为m份 使各份的和相等 求m的最大值 比如 3 2 4 3 6 可以分成 3 2 4 3 6 m 1 3 6 2 4 3 m 2 3 3 2 4 6 m 3 所以m的最大值为3 算法 原理的思想是
  • 树06--二叉树中和为某一值的路径

    树06 二叉树中和为某一值的路径 jz24 题目概述 解析 参考答案 注意事项 说明 题目概述 算法说明 输入一颗二叉树的根节点和一个整数 按字典序打印出二叉树中结点值的和为输入整数的所有路径 路径定义为从树的根结点开始往下一直到叶结点所经
  • Sort List

    Sort a linked list in O n log n time using constant space complexity 题目要求用 O n log n 的时间复杂度和常数的空间复杂度来进行链表排序 O nlogn 的排序算
  • 数据结构之链表与线性表

    数据结构之链表与线性表 线性表 顺序线性表 顺序表 顺序线性表 使用数组实现 一组地址连续的存储单元 数组大小有两种方式指定 一是静态分配 二是动态扩展 优点 随机访问特性 查找O 1 时间 存储密度高 逻辑上相邻的元素 物理上也相邻 缺点
  • Hash table and application in java

    查找的效率取决于在查找是比较的次数 次数越少效率越高 反之越低 最理想的情况是无需比较 一次存取便能找到所查找的记录 根据对应关系f找到给定值K的像f K hash function 应运而生 由此思想建的表称为hash table 集合h
  • PCL—低层次视觉—点云分割(RanSaC)

    点云分割 点云分割可谓点云处理的精髓 也是三维图像相对二维图像最大优势的体现 不过多插一句 自Niloy J Mitra教授的Global contrast based salient region detection出现 最优分割到底鹿死
  • 微软2013暑假实习生笔试题

    自己mark一下 以作后备 下面提交原文链接 原文博客 部分题目答案不确定 会持续更新 1 Which of the following calling convention s support s supportvariable leng
  • Python 实现列队

    1 列队定义 队列是项的有序结合 其中添加新项的一端称为队尾 移除项的一端称为队首 当一个元素从队尾进入队列时 一直向队首移动 直到它成为下一个需要移除的元素为止 最近添加的元素必须在队尾等待 集合中存活时间最长的元素在队首 这种排序成为
  • 数据结构与算法书籍推荐

    学习数据结构与算法 还是很有必要看几本相关的书籍 但根据不同基础的人 合适看的书也不一样 因此 针对不同层次 不同语言的人 推荐几本市面上口碑不错的书 1 入门级 针对刚入门的同学 建议不要急着去看那些经典书 像 算法导论 算法 这些比较经
  • 以太坊系列之十五: 以太坊数据库

    以太坊数据库中都存了什么 以太坊使用的数据库是一个NOSQL数据库 是谷歌提供的开源数据leveldb 这里尝试通过分析以太坊数据库存储了什么来分析以太坊可能为我们提供哪些关于区块链的API 存储内容 NOSQL是一个key value数据
  • Linux 内核中的 Device Mapper 机制

    Linux 内核中的 Device Mapper 机制 尹 洋 在读博士生 尹洋 中科院计算所国家高性能计算机工程技术研究中心的在读博士生 主要从事服务部署和存储资源管理以及Linux块设备一级的开发和研究工作 简介 本文结合具体代码对 L
  • Linux下进程退出的几种形式

    进程退出 Linux 下进程的退出分为正常退出和异常退出两种 1 正常退出 a 在main 函数中执行return b 调用exit 函数 c 调用 exit 函数 2 异常退出 a 调用about函数 b 进程收到某个信号 而该信号使程序
  • Leetcode2661. 找出叠涂元素

    Every day a Leetcode 题目来源 2661 找出叠涂元素 解法1 哈希 题目很绕 理解题意后就很简单 由于矩阵 mat 中每一个元素都不同 并且都在数组 arr 中 所以首先我们用一个哈希表 hash 来存储 mat 中每
  • 从源码角度来谈谈 HashMap

    HashMap的知识点可以说在面试中经常被问到 是Java中比较常见的一种数据结构 所以这一篇就通过源码来深入理解下HashMap 1 HashMap的底层是如何实现的 基于JDK8 1 1 HashMap的类结构和成员 HashMap继承
  • 浅谈归并排序:合并 K 个升序链表的归并解法

    在面试中遇到了这道题 如何实现多个升序链表的合并 这是 LeetCode 上的一道原题 题目具体如下 用归并实现合并 K 个升序链表 LeetCode 23 合并K个升序链表 给你一个链表数组 每个链表都已经按升序排列 请你将所有链表合并到
  • 最大流-Dinic算法,原理详解,四大优化,详细代码

    文章目录 零 前言 一 概念回顾 可略过 1 1流网络 1 2流 1 3最大流 1 4残留网络 1 5增广路

随机推荐

  • Android平台安全(一)

    刚好五一了 已经过去两三天了 今天接触到了关于Android安全的一些东西 记录下来 Android安全我大致分三个部分来说明 今天我就先说第一个部分 在典型的场景中 安全主要用于解决一下4类需求 保密 鉴别 认证 完整性 不可以否认性 安
  • IncrediBuild 联合编译

    01 基本信息 官网 https www incredibuild com Make 和其他构建工具示例 要使用IncrediBuild 必须有License 可以免费申请试用版本的license 可以到 https www incredi
  • 【H5】两种加密解密方法:

    H5 两种加密解码方法 encodeURI 加密 decodeURI 解密 加密成base64编码格式 btoa 加密 atob 解密 实现代码如下
  • 【C语言】计数排序

    一 算法描述 得到最小值和最大值 即得到临时数组的长度 数等于临时数组的下标 下标对应的值就加一 把临时数组的信息对应到原数组中 计数排序有很大的约束 最小值和最大值不能相差很大 排序的数适用于非负数 否则得另加代码将负数偏移为正数 最后还
  • MySQL——存储过程详解及实例分析

    目录 一 储存过程简介 1 什么是存储过程 2 存储过程优缺点 3 存储过程入门程序 4 在idea中如何调用储存过程 二 存储过程编程 1 存储过程的变量 2 存储过程中的参数 3 选择结构if 4 分支结构case 5 3个循环结构 6
  • 中文分词jieba学习笔记

    中文分词jieba学习笔记 一 分词模式 二 自定义词典 2 1 命令 2 2 使用方式 三 关键词抽取 基于TF IDF算法 3 1 用jieba analyse extract tags 3 2 用jieba analyse textr
  • idea配置tomcat启动服务器时控制台乱码

    项目场景 在idea中配置tomcat启动时候控制台乱码问题 问题描述 idea中以tomcat启动控制台出现乱码问题 原因分析 由于tomcat8以后默认编码格式是utf 8 tomcat7之前的都是iso8859 1 与idea中的编码
  • 反激式开关电源双环PID(电压环+电流环)控制之MATLAB仿真

    前面一篇文章我讲解了反激式开关电源输出电压的pid控制的matlab仿真 反激式开关电源输出电压PID控制的MATLAB仿真 我只对输出电压做了控制 不管负载多大 只要在设计功率之内 都能把电压维持在12V 但在实际电路设计中 我们还需要考
  • Box2D C++ 教程 第五节:物体(Bodies)

    Box2D C 教程 第五节 物体 Bodies 作者 firedragonpzy 14 十一月 2012 暂无评论 声明 本教程翻译自 Box2D C tutorials Bodies 仅供学习参考 物体 Bodies 物体是物理场景中的
  • 【踩坑】jmeter提取token,响应body中全部是token无法用正则提取

    情况是这样的 这是jmeter的响应结果 响应所有文本都是token 尝试了多次用正则提取 均无法提取全部body 经过查询资料 使用BeanShell 后置处理程序 import org json JSONObject import or
  • 【数据分析】【Pandas】(一)如何制作频率分布直方图

    文章目录 概述 1 直方图 2 密度图 概述 计算一组数据的分布有助于我们更好的了解数据构成 我们可以通过直方图或密度图 将离散的数据通过连续的方式展现出来 数据分布 频数分布 在各组按顺序排列的基础上 列出每个组的总体单位数 形成一个数列
  • nuxtjs 国际化i18n

    1 设置国际化匹配文字 locales zh json locales en json 英文同理 topbar home 首页 pin 沸点 topic 话题 book 小册 search 搜索 menu home 我的主页 label 标
  • 【计算机毕业设计】高校信息资源共享平台

    高校信息资源共享平台 21世纪的今天 随着社会的不断发展与进步 人们对于信息科学化的认识 已由低层次向高层次发展 由原来的感性认识向理性认识提高 管理工作的重要性已逐渐被人们所认识 科学化的管理 使信息存储达到准确 快速 完善 并能提高工作
  • 什么是企业用户画像,怎么构建企业用户画像

    企业画像 简单说 企业给人的印象 可以跟自然人的用户画像相类比 这其实是IT行业的一种叫法 在金融行业 一般叫做 尽职调查报告 当然 尽职调查报告只需要尽职 不需要说的太具体或者太难看 什么是企业用户画像 企业用户画像与个人用户画像有很大区
  • 反射/存储/DOM型XSS攻击原理及攻击流程详解

    文章目录 XSS漏洞原理 1 XSS分类 1 1 攻击流程 2 存储型XSS 2 1 攻击流程 3 DOM型XSS 3 1 攻击流程 XSS修复 XSS漏洞原理 XSS 跨站脚本攻击 是一种常见的 Web 安全漏洞 其允许攻击者在恶意用户的
  • 新版caffe添加自己的层(目前只学会添加,我想要添加的loss还没能实现)

    今天实现了在caffe框架中加入一个层 完成欧式距离的任务 之所以这样 是因为还没有实现自己想要的loss 只是试着学者 看能不能把添加层的流程顺下来 最后实现了 一 总体框架 1 在 src caffe proto caffe proto
  • SpringCache的介绍和使用

    1 简介 1 Spring 从 3 1 开始定义了 org springframework cache Cache和 org springframework cache CacheManager 接口来统一不同的缓存技术 并支持使用 JCa
  • 六、IP地址子网划分与VLAN

    一 IP地址的五大分类 概念 IP地址相当于人的身份证 用于在TCP IP通信协议中标记每台计算机的地址 通常用于十进制来表示 如192 168 1 100 但是在计算机内部 IP地址是一个32位的二进制数值 如11000000 10101
  • [转载]Chrome 与 Chrome OS 各版本下载集合

    Chrome OS 下载 由 Hexxeh提供的第三方编译版本 Chrome OS USB 镜像 点击这里 Chrome OS WMware 镜像 点击这里 Chrome OS Vanilla USB VMWare VirtualBox 点
  • 树的遍历-深度优先遍历和广度优先遍历

    深度优先遍历类似于树的先序遍历 假设给定初态是图中所有顶点均未被访问过 从图中某一顶点vi出发遍历图中的定义如下 首先访问出发点vi 并将其访问标志置为1 然后 从vi出发点依次搜索vi的每个邻接点vj 如vj未被访问过 则以vj为新的出发