数据结构 排序讲解
- 格式:ppt
- 大小:1.23 MB
- 文档页数:26
数据结构先序中序后序理解数据结构是计算机科学中的重要概念之一,它是指一组数据的组织方式以及对这组数据进行操作的方法。
在学习数据结构的过程中,我们经常会遇到先序、中序和后序这三个概念。
它们是用来描述二叉树的遍历方式的,也可以用来表示表达式的计算顺序。
本文将从先序、中序和后序这三个角度来解释数据结构的含义和应用。
一、先序遍历先序遍历是指按照根节点、左子树、右子树的顺序访问二叉树的节点。
在先序遍历中,我们首先访问根节点,然后递归地遍历左子树和右子树。
先序遍历的应用非常广泛,比如在文件系统的目录结构中,我们可以使用先序遍历来列出所有的文件和文件夹。
二、中序遍历中序遍历是指按照左子树、根节点、右子树的顺序访问二叉树的节点。
在中序遍历中,我们首先递归地遍历左子树,然后访问根节点,最后再递归地遍历右子树。
中序遍历在二叉搜索树的操作中非常常见,它可以按照从小到大的顺序输出二叉搜索树中的元素。
三、后序遍历后序遍历是指按照左子树、右子树、根节点的顺序访问二叉树的节点。
在后序遍历中,我们首先递归地遍历左子树和右子树,最后访问根节点。
后序遍历常用于对二叉树进行一些计算操作,比如计算二叉树的深度、判断二叉树是否对称等。
除了用于二叉树的遍历,先序、中序和后序还可以用来表示表达式的计算顺序。
在数学表达式中,运算符和操作数之间的顺序非常重要,它决定了表达式的计算结果。
先序、中序和后序可以用来表示运算符的位置,从而决定表达式的计算顺序。
先序表示法中,运算符位于操作数之前,如"+ 3 4"表示加法运算。
中序表示法中,运算符位于操作数之间,如"3 + 4"表示加法运算。
后序表示法中,运算符位于操作数之后,如"3 4 +"表示加法运算。
不同的表示法对应着不同的计算顺序,但它们都能得到相同的结果。
先序、中序和后序在数据结构中有着广泛的应用。
它们不仅仅是一种遍历方式,还可以表示表达式的计算顺序。
数据结构课程设计—内部排序算法比较在计算机科学领域中,数据的排序是一项非常基础且重要的操作。
内部排序算法作为其中的关键部分,对于提高程序的运行效率和数据处理能力起着至关重要的作用。
本次课程设计将对几种常见的内部排序算法进行比较和分析,包括冒泡排序、插入排序、选择排序、快速排序和归并排序。
冒泡排序是一种简单直观的排序算法。
它通过重复地走访要排序的数列,一次比较两个数据元素,如果顺序不对则进行交换,并一直重复这样的走访操作,直到没有要交换的数据元素为止。
这种算法的优点是易于理解和实现,但其效率较低,在处理大规模数据时性能不佳。
因为它在最坏情况下的时间复杂度为 O(n²),平均时间复杂度也为O(n²)。
插入排序的工作原理是通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入,直到整个序列有序。
插入排序在数据量较小时表现较好,其平均时间复杂度和最坏情况时间复杂度也都是 O(n²),但在某些情况下,它的性能可能会优于冒泡排序。
选择排序则是每一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,然后,再从剩余未排序元素中继续寻找最小(或最大)元素,然后放到已排序序列的末尾。
以此类推,直到全部待排序的数据元素排完。
选择排序的时间复杂度同样为O(n²),但它在某些情况下的交换操作次数可能会少于冒泡排序和插入排序。
快速排序是一种分治的排序算法。
它首先选择一个基准元素,将数列分成两部分,一部分的元素都比基准小,另一部分的元素都比基准大,然后对这两部分分别进行快速排序。
快速排序在平均情况下的时间复杂度为 O(nlogn),最坏情况下的时间复杂度为 O(n²)。
然而,在实际应用中,快速排序通常表现出色,是一种非常高效的排序算法。
归并排序也是一种分治算法,它将待排序序列分成若干个子序列,每个子序列有序,然后将子序列合并成一个有序序列。
数据结构第9章排序数据结构第9章排序第9章排名本章主要内容:1、插入类排序算法2、交换类排序算法3、选择类排序算法4、归并类排序算法5、基数类排序算法本章重点难点1、希尔排序2、快速排序3、堆排序4.合并排序9.1基本概念1.关键字可以标识数据元素的数据项。
如果一个数据项可以唯一地标识一个数据元素,那么它被称为主关键字;否则,它被称为次要关键字。
2.排序是把一组无序地数据元素按照关键字值递增(或递减)地重新排列。
如果排序依据的是主关键字,排序的结果将是唯一的。
3.排序算法的稳定性如果要排序的记录序列中多个数据元素的关键字值相同,且排序后这些数据元素的相对顺序保持不变,则称排序算法稳定,否则称为不稳定。
4.内部排序与外部排序根据在排序过程中待排序的所有数据元素是否全部被放置在内存中,可将排序方法分为内部排序和外部排序两大类。
内部排序是指在排序的整个过程中,待排序的所有数据元素全部被放置在内存中;外部排序是指由于待排序的数据元素个数太多,不能同时放置在内存,而需要将一部分数据元素放在内存中,另一部分放在外围设备上。
整个排序过程需要在内存和外存之间进行多次数据交换才能得到排序结果。
本章仅讨论常用的内部排序方法。
5.排序的基本方法内部排序主要有5种方法:插入、交换、选择、归并和基数。
6.排序算法的效率评估排序算法的效率主要有两点:第一,在一定数据量的情况下,算法执行所消耗的平均时间。
对于排序操作,时间主要用于关键字之间的比较和数据元素的移动。
因此,我们可以认为一个有效的排序算法应该是尽可能少的比较和数据元素移动;第二个是执行算法所需的辅助存储空间。
辅助存储空间是指在一定数据量的情况下,除了要排序的数据元素所占用的存储空间外,执行算法所需的存储空间。
理想的空间效率是,算法执行期间所需的辅助空间与要排序的数据量无关。
7.待排序记录序列的存储结构待排序记录序列可以用顺序存储结构和和链式存储结构表示。
在本章的讨论中(除基数排序外),我们将待排序的记录序列用顺序存储结构表示,即用一维数组实现。
数据结构之拓扑排序算法详解拓扑排序算法是一种常用于有向无环图(DAG)的排序算法,它可以将图中的顶点按照一定的顺序进行排序,使得图中任意一条有向边的起点在排序结果中都排在终点的前面。
在实际应用中,拓扑排序算法常用于解决任务调度、依赖关系分析等问题。
本文将详细介绍拓扑排序算法的原理、实现方法以及应用场景。
### 一、拓扑排序算法原理拓扑排序算法的原理比较简单,主要包括以下几个步骤:1. 从DAG图中选择一个入度为0的顶点并输出。
2. 从图中删除该顶点以及以该顶点为起点的所有有向边。
3. 重复步骤1和步骤2,直到图中所有顶点都被输出。
### 二、拓扑排序算法实现下面以Python语言为例,给出拓扑排序算法的实现代码:```pythondef topological_sort(graph):in_degree = {v: 0 for v in graph}for u in graph:for v in graph[u]:in_degree[v] += 1queue = [v for v in graph if in_degree[v] == 0] result = []while queue:u = queue.pop(0)result.append(u)for v in graph[u]:in_degree[v] -= 1if in_degree[v] == 0:queue.append(v)if len(result) == len(graph):return resultelse:return []# 测试代码graph = {'A': ['B', 'C'],'B': ['D'],'C': ['D'],'D': []}print(topological_sort(graph))```### 三、拓扑排序算法应用场景拓扑排序算法在实际应用中有着广泛的应用场景,其中包括但不限于以下几个方面:1. 任务调度:在一个任务依赖关系图中,拓扑排序可以确定任务的执行顺序,保证所有任务按照依赖关系正确执行。
前序后序中序详细讲解1.引言1.1 概述在数据结构与算法中,前序、中序和后序是遍历二叉树的三种基本方式之一。
它们是一种递归和迭代算法,用于按照特定的顺序访问二叉树的所有节点。
通过遍历二叉树,我们可以获取有关树的结构和节点之间关系的重要信息。
前序遍历是指先访问根节点,然后递归地访问左子树,最后递归地访问右子树。
中序遍历是指先递归地访问左子树,然后访问根节点,最后递归地访问右子树。
后序遍历是指先递归地访问左子树,然后递归地访问右子树,最后访问根节点。
它们的不同之处在于访问根节点的时机不同。
前序遍历可以帮助我们构建二叉树的镜像,查找特定节点,或者获取树的深度等信息。
中序遍历可以帮助我们按照节点的大小顺序输出树的节点,或者查找二叉搜索树中的某个节点。
后序遍历常用于删除二叉树或者释放二叉树的内存空间。
在实际应用中,前序、中序和后序遍历算法有着广泛的应用。
它们可以用于解决树相关的问题,例如在Web开发中,树结构的遍历算法可以用于生成网页导航栏或者搜索树结构中的某个节点。
在图像处理中,前序遍历可以用于图像压缩或者图像识别。
另外,前序和后序遍历算法还可以用于表达式求值和编译原理中的语法分析等领域。
综上所述,前序、中序和后序遍历算法是遍历二叉树的重要方式,它们在解决各种与树有关的问题中扮演着关键的角色。
通过深入理解和应用这些遍历算法,我们可以更好地理解和利用二叉树的结构特性,并且能够解决更加复杂的问题。
1.2文章结构文章结构是指文章中各个部分的布局和组织方式。
一个良好的文章结构可以使读者更好地理解和理解文章的内容。
本文将详细讲解前序、中序和后序三个部分的内容和应用。
首先,本文将在引言部分概述整篇文章的内容,并介绍文章的结构和目的。
接下来,正文部分将分为三个小节,分别对前序、中序和后序进行详细讲解。
在前序讲解部分,我们将定义和解释前序的意义,并介绍前序在实际应用中的场景。
通过详细的解释和实例,读者将能更好地理解前序的概念和用途。
数据结构的常用算法一、排序算法排序算法是数据结构中最基本、最常用的算法之一。
常见的排序算法有冒泡排序、选择排序、插入排序、快速排序、归并排序等。
1. 冒泡排序冒泡排序是一种简单的排序算法,它重复地比较相邻的两个元素,如果它们的顺序错误就将它们交换过来。
通过多次的比较和交换,最大(或最小)的元素会逐渐“浮”到数列的顶端,从而实现排序。
2. 选择排序选择排序是一种简单直观的排序算法,它每次从待排序的数据中选择最小(或最大)的元素,放到已排序序列的末尾,直到全部元素排序完毕。
3. 插入排序插入排序是一种简单直观的排序算法,它将待排序的数据分为已排序区和未排序区,每次从未排序区中取出一个元素,插入到已排序区的合适位置,直到全部元素排序完毕。
4. 快速排序快速排序是一种常用的排序算法,它采用分治的思想,通过一趟排序将待排序的数据分割成独立的两部分,其中一部分的所有数据都比另一部分小,然后再按此方法对这两部分数据进行快速排序,递归地进行,最终实现整个序列有序。
5. 归并排序归并排序是一种稳定的排序算法,它采用分治的思想,将待排序的数据分成若干个子序列,分别进行排序,然后将排好序的子序列合并成更大的有序序列,直到最终整个序列有序。
二、查找算法查找算法是在数据结构中根据给定的某个值,在数据集合中找出目标元素的算法。
常见的查找算法有线性查找、二分查找、哈希查找等。
1. 线性查找线性查找是一种简单直观的查找算法,它从数据集合的第一个元素开始,依次比较每个元素,直到找到目标元素或遍历完整个数据集合。
2. 二分查找二分查找是一种高效的查找算法,它要求数据集合必须是有序的。
通过不断地将数据集合分成两半,将目标元素与中间元素比较,从而缩小查找范围,最终找到目标元素或确定目标元素不存在。
3. 哈希查找哈希查找是一种基于哈希表的查找算法,它通过利用哈希函数将目标元素映射到哈希表中的某个位置,从而快速地找到目标元素。
三、图算法图算法是解决图结构中相关问题的算法。
数组的排序方法数组是一种常见的数据结构,它由一系列元素组成,每个元素都有一个索引。
我们经常需要对数组进行排序,以便更好地利用数组中的数据。
本文将介绍几种常见的数组排序方法,包括冒泡排序、选择排序、插入排序、快速排序和归并排序。
一、冒泡排序冒泡排序是一种简单的排序算法,它的原理是通过不断比较相邻的元素,将较大的元素逐步移动到数组的末尾。
具体的步骤如下:1. 从数组的第一个元素开始,依次比较相邻的两个元素。
2. 如果前一个元素大于后一个元素,则交换它们的位置。
3. 继续向后比较,直到将最大的元素移动到数组的末尾。
4. 重复以上步骤,直到所有元素都按照从小到大的顺序排列。
二、选择排序选择排序也是一种简单的排序算法,它的原理是通过不断选择最小的元素,将其放置到数组的最前面。
具体的步骤如下:1. 遍历整个数组,找到最小的元素。
2. 将最小的元素与数组的第一个元素交换位置。
3. 接着从第二个元素开始,再次找到最小的元素,将其与数组的第二个元素交换位置。
4. 重复以上步骤,直到所有元素都按照从小到大的顺序排列。
三、插入排序插入排序是一种简单但有效的排序算法,它的原理是将一个新的元素插入到已经排好序的部分数组中。
具体的步骤如下:1. 从数组的第二个元素开始,将其与已经排好序的部分数组进行比较。
2. 如果待插入的元素小于已排序部分的某个元素,则将该元素后移一位。
3. 将待插入的元素插入到正确的位置。
4. 重复以上步骤,直到所有元素都按照从小到大的顺序排列。
四、快速排序快速排序是一种高效的排序算法,它的原理是通过分治法将数组分割成较小的子数组,然后分别对子数组进行排序。
具体的步骤如下:1. 选择一个基准元素,将数组分成两部分,一部分小于基准元素,一部分大于基准元素。
2. 对这两部分分别进行快速排序,即递归地对子数组进行排序。
3. 将两部分排好序的子数组合并起来,得到最终的排序结果。
五、归并排序归并排序是一种稳定的排序算法,它的原理是将数组分成两个子数组,分别对其进行排序,然后将两个子数组合并成一个有序数组。
数据结构简单排序一、简介数据结构是计算机科学中重要的概念之一,它用于组织和存储数据,以便于访问和修改。
而排序算法则是数据结构中的重要内容,它可以将无序的数据按照特定规则进行排列,提高数据的查找和处理效率。
本文将介绍数据结构中的简单排序算法。
二、冒泡排序冒泡排序是最基础的排序算法之一,它通过不断比较相邻元素并交换位置,将较大或较小的元素逐步“冒泡”到数组的末尾或开头。
具体步骤如下:1. 从数组第一个元素开始比较相邻元素。
2. 如果前一个元素大于后一个元素,则交换它们的位置。
3. 继续向后比较相邻元素,并交换位置直到最后一个元素。
4. 重复以上步骤直到整个数组有序。
三、选择排序选择排序也是一种简单且常用的排序算法。
它通过不断寻找最小值或最大值,并将其放在已排好序部分的末尾或开头。
具体步骤如下:1. 找到当前未排序部分中最小值(或最大值)。
2. 将该值与未排序部分第一个元素交换位置。
3. 将已排序部分的末尾(或开头)指针向后(或前)移动一位。
4. 重复以上步骤直到整个数组有序。
四、插入排序插入排序是一种简单但高效的排序算法,它通过将未排序部分中的每个元素插入已排好序部分中的合适位置,逐步构建一个有序数组。
具体步骤如下:1. 将第一个元素视为已排好序部分,将第二个元素作为未排序部分中的第一个元素。
2. 将未排序部分中的第一个元素插入已排好序部分中合适的位置。
3. 将已排好序部分扩展至包含前两个元素,并将未排序部分中的下一个元素插入到合适位置。
4. 重复以上步骤直到整个数组有序。
五、希尔排序希尔排序是一种高效且简单的改进版插入排序算法。
它通过对数据进行多次局部交换和移动,使得数据更快地接近有序状态。
具体步骤如下:1. 定义一个增量值h,将数组按照间隔h划分成若干子数组。
2. 对每个子数组进行插入排序操作。
3. 缩小增量h,重复以上操作直到h=1。
4. 对整个数组进行插入排序操作。
六、归并排序归并排序是一种高效且稳定的排序算法。
数据结构-王道-排序排序直接插⼊排序从上⾯的插⼊排序思想中,不难得到⼀种简单直接的插⼊排序算法。
假设待排序表在某次过程中属于这种情况。
|有序序列L[1…i−1]|L(i)|⽆序序列L[i+1…n]||:-|:-|为了实现将元素L(i)插⼊到已有序的⼦序列L[1…i−1]中,我们需要执⾏以下操作(为了避免混淆,下⾯⽤L[]表⽰⼀个表,⽽⽤L()表⽰⼀个元素):查找出L(i)在L[i+1…n]中的插⼊位置k。
将L[k…i−1]中所有元素全部后移⼀个位置。
将L(i)赋值到L(k)void InserSort(int A[],int n){int i,j;for(i=2;i<=n;i++){if(A[i]<A[i-1]){A[0]=A[i];for(j=i-1;A[0]<A[j];j--)A[j+1]=A[j];A[j+1]=A[0];}}}折半插⼊排序从前⾯的直接插⼊排序算法中,不难看出每趟插⼊的过程,都进⾏了两项⼯作:从前⾯的⼦表中查找出待插⼊元素应该被插⼊的位置。
给插⼊位置腾出空间,将待插⼊元素复制到表中的插⼊位置。
注意到该算法中,总是边⽐较边移动元素,下⾯将⽐较和移动操作分离开,即先折半查找出元素的待插⼊位置,然后再同意的移动待插⼊位置之后的元素。
void InserSort(int A[],int n){int i,j,low,high,mid;for(i=2;i<=n;i++){A[0]=A[i];low=1,high=i-1;while(low<=high){mid=(low+high)/2;if(A[mid]>A[0])high=mid-1;elselow=mid+1;}for(j=i-1;j>=high+1;j--)A[j+1]=A[j];A[high+1]=A[0];}}折半插⼊排序从前⾯的代码原理中不难看出,直接插⼊排序适⽤于基本有序的排序表和数据量不⼤的排序表。
数据结构先序中序后序理解一、先序遍历先序遍历是指首先访问根节点,然后按照先序遍历的方式遍历左子树,最后再遍历右子树。
具体来说,先序遍历的顺序是根节点→左子树→右子树。
先序遍历的特点是能够保证根节点最先被访问,适用于需要先处理根节点的场景。
先序遍历常用的应用场景包括二叉树的构建和重建、表达式的求值和转换、图的深度优先搜索等。
在二叉树的构建和重建中,先序遍历可以用来确定根节点的位置,进而构建整棵二叉树。
而在表达式的求值和转换中,先序遍历可以将中缀表达式转换为后缀表达式,方便进行求值。
在图的深度优先搜索中,先序遍历可以帮助我们找到从起始节点出发的所有路径。
二、中序遍历中序遍历是指先遍历左子树,然后访问根节点,最后再遍历右子树。
具体来说,中序遍历的顺序是左子树→根节点→右子树。
中序遍历的特点是能够保证节点按照从小到大的顺序被访问,适用于需要按照顺序处理节点的场景。
中序遍历常用的应用场景包括二叉搜索树的操作、中序表达式的求值和转换等。
在二叉搜索树的操作中,中序遍历可以按照从小到大的顺序输出树中的所有节点,方便进行查找和排序操作。
在中序表达式的求值和转换中,中序遍历可以将中缀表达式转换为前缀或后缀表达式,方便进行求值。
三、后序遍历后序遍历是指先遍历左子树,然后遍历右子树,最后访问根节点。
具体来说,后序遍历的顺序是左子树→右子树→根节点。
后序遍历的特点是能够保证根节点最后被访问,适用于需要先处理子节点的场景。
后序遍历常用的应用场景包括二叉树的销毁和释放、表达式树的构建等。
在二叉树的销毁和释放中,后序遍历可以先销毁子节点,最后释放根节点的内存,避免内存泄漏。
在表达式树的构建中,后序遍历可以根据后缀表达式构建整棵表达式树,方便进行表达式的求值。
先序遍历、中序遍历和后序遍历是数据结构中常用的三种遍历方式。
它们各自具有不同的特点和应用场景,能够帮助我们更好地处理和操作数据。
在实际应用中,我们需要根据具体的需求选择合适的遍历方式,以达到最优的效果。
数据结构八大排序之冒泡排序算法冒泡排序是一种经典的排序算法,它基于比较和交换的思想,简单易懂却非常高效。
在实际应用中,我们经常会遇到需要对一组数据进行排序的情况,而冒泡排序就是解决这个问题的利器。
首先,我们来了解一下冒泡排序的基本原理。
冒泡排序的核心思想是通过相邻元素的比较和交换,将较大的元素逐渐“冒泡”到数组的末尾,达到排序的目的。
具体来说,算法从数组的第一个元素开始,比较相邻的两个元素,如果前一个元素大于后一个元素,则交换它们的位置;如果前一个元素小于等于后一个元素,则位置不变。
通过一轮比较后,最大的元素就会“冒泡”到数组的末尾。
然后,算法再从数组的第一个元素开始进行下一轮比较,依次类推,直到所有元素都排好序。
接下来,我们详细了解冒泡排序的具体步骤。
假设我们需要对一个由n个元素组成的数组进行排序,首先,我们需要进行n-1轮的比较。
每一轮比较都从数组的第一个元素开始,比较相邻的两个元素,根据大小进行交换或保持不变。
一轮比较下来,最大的元素就会“冒泡”到数组的末尾。
然后,下一轮比较就会从数组的第一个元素到倒数第二个元素进行,以此类推,直到最后一轮只需要比较数组的前两个元素。
冒泡排序的时间复杂度为O(n²),这是因为每一轮比较需要遍历整个数组,而总共需要进行n-1轮比较。
在最好的情况下,也就是数组已经排好序的情况下,冒泡排序的时间复杂度可以优化到O(n)。
然而,在最坏的情况下,即数组完全逆序的情况下,冒泡排序的性能较差。
冒泡排序是一种稳定的排序算法,这意味着相等元素的相对顺序不会被改变。
冒泡排序的思想简单直观,实现也相对简单,所以它在教学和入门级应用中被广泛使用。
然而,在大规模数据的排序中,由于其时间复杂度较高,冒泡排序的效率相对较低。
除了基本的冒泡排序算法,还有一些优化的方法可以进一步提高算法的效率。
例如,我们可以设置一个标志位来判断一轮比较中是否进行了交换,如果没有交换,说明数组已经有序,可以提前结束排序。
数据结构中的树、图、查找、排序在计算机科学中,数据结构是组织和存储数据的方式,以便能够有效地对数据进行操作和处理。
其中,树、图、查找和排序是非常重要的概念,它们在各种算法和应用中都有着广泛的应用。
让我们先来谈谈树。
树是一种分层的数据结构,就像是一棵倒立的树,有一个根节点,然后从根节点向下延伸出许多分支节点。
比如一个家族的族谱,就可以用树的结构来表示。
最上面的祖先就是根节点,他们的后代就是分支节点。
在编程中,二叉树是一种常见的树结构。
二叉树的每个节点最多有两个子节点,分别称为左子节点和右子节点。
二叉搜索树是一种特殊的二叉树,它具有特定的性质,即左子树中的所有节点值都小于根节点的值,而右子树中的所有节点值都大于根节点的值。
这使得在二叉搜索树中查找一个特定的值变得非常高效。
二叉搜索树的插入和删除操作也相对简单。
插入时,通过比较要插入的值与当前节点的值,确定往左子树还是右子树移动,直到找到合适的位置插入新节点。
删除节点则稍微复杂一些,如果要删除的节点没有子节点,直接删除即可;如果有一个子节点,用子节点替换被删除的节点;如果有两个子节点,通常会找到右子树中的最小节点来替换要删除的节点,然后再删除那个最小节点。
接下来,我们聊聊图。
图是由顶点(也称为节点)和边组成的数据结构。
顶点代表对象,边则表示顶点之间的关系。
比如,社交网络中的用户可以看作顶点,用户之间的好友关系就是边。
图可以分为有向图和无向图。
有向图中的边是有方向的,就像单行道;无向图的边没有方向,就像双向车道。
图的存储方式有邻接矩阵和邻接表等。
邻接矩阵用一个二维数组来表示顶点之间的关系,如果两个顶点之间有边,对应的数组元素为 1,否则为 0。
邻接表则是为每个顶点建立一个链表,链表中存储与该顶点相邻的顶点。
图的遍历是图算法中的重要操作,常见的有深度优先遍历和广度优先遍历。
深度优先遍历就像是沿着一条路一直走到底,然后再回头找其他路;广度优先遍历则是先访问距离起始顶点近的顶点,再逐步扩展到更远的顶点。