基本算法
算法是计算的命脉。它们是计算机解决问题、分析数据和做出决策时遵循的逐步指令。就像菜谱一样,它们将复杂的任务分解成可管理的程序。理解这些基本算法是掌握计算机科学和编程的基石。
1.搜索算法:
搜索是什么?
搜索是在数据集合中定位特定元素或项的基本过程。这些数据集合可以采用多种形式,例如数组、列表、树或其他结构化表示。搜索的主要目标是确定所需元素是否存在于数据中,如果存在,则确定其精确位置或检索它。它在各种计算任务和实际应用中发挥着重要作用,包括信息检索、数据分析、决策过程等等。
搜索算法简介
所有搜索算法都使用搜索键来执行搜索过程。搜索算法预期返回成功或失败状态,通常用布尔值 true/false 表示。搜索算法种类繁多,其性能和效率取决于数据及其使用方式。
线性搜索算法被认为是所有搜索算法中最基本的。最好的算法或许是二分搜索。还有其他搜索算法,例如深度优先搜索算法、广度优先算法等。搜索算法的效率是通过在最坏情况下比较搜索键的次数来衡量的。搜索算法中使用的符号是 O(n),其中 n 是执行的比较次数。它给出了在给定条件下算法所需执行时间的渐近上限的概念。
搜索算法中的搜索情况可以分为最佳情况、平均情况和最坏情况。在某些算法中,这三种情况可能渐近相同,而在其他一些算法中,这三种情况可能存在很大差异。搜索算法的平均行为有助于确定算法的有效性。
摘要:搜索算法是用于在数据集合中定位特定数据的逐步过程。它被认为是计算中的一个基本过程。在计算机科学中,在搜索数据时,应用程序的快慢通常取决于是否使用了合适的搜索算法。
术语:
- 目标元素:这就是您要寻找的宝藏!它是您想要在集合中找到的特定数据。想象一下搜索电话簿——目标元素是某个人的电话号码。
- 搜索空间:可以将其想象成大海捞针的地方。它代表了您正在搜索的整个数据集合。这可能是一个数字数组、一个名称列表,或者更复杂的数据结构。
- 复杂度:这指的是搜索算法所需的工作量。这就像衡量图书管理员需要做多少工作才能找到你的书一样。复杂度通常以时间(找到目标所需的时间)和空间(算法需要多少额外内存)来衡量。
- 确定性与非确定性:搜索算法可以像遵循菜谱(确定性)或进行有根据的猜测(非确定性)。确定性算法总是遵循相同的清晰步骤,例如二分查找,它不断将搜索空间一分为二。非确定性算法,例如线性查找,在最坏的情况下可能需要检查整个集合。
实际应用
-
信息检索:想象一下在网上搜索一个特定的食谱。像谷歌这样的搜索引擎利用复杂的搜索算法来筛选海量数据集,索引网站和内容。当你输入查询时,这些算法会识别与你的搜索词最相关的网页,并在几分之一秒内提供你所需的信息。
-
数据库系统:数据库存储着海量信息,从客户记录到金融交易,无所不包。搜索算法是高效数据检索的基石。当您在数据库管理系统中提交查询时,搜索算法会快速找到符合条件的特定记录,从而节省您的时间和精力。
-
电子商务:高效的搜索是网上购物蓬勃发展的关键。电商平台使用搜索算法来帮助您找到理想的产品。它们允许您根据价格、品牌或颜色等各种条件进行筛选和搜索。在后台,搜索算法驱动着这些筛选器,精准定位符合您偏好的产品,让您的购物体验顺畅高效。
-
网络:互联网是一个由互连设备组成的复杂网络。搜索算法在高效路由数据包方面发挥着至关重要的作用。它们有助于确定信息在网络中传输的最佳路径,确保您的视频通话或在线游戏顺畅运行。
-
人工智能 (AI):人工智能正在革新许多领域。搜索算法是人工智能应用的基本工具。它们使人工智能系统能够解决问题、做出决策,甚至进行象棋等游戏。通过高效地搜索海量数据并识别模式,搜索算法为人工智能背后的智能化做出了贡献。
-
模式识别:模式识别使计算机能够识别和理解数据(例如图像、语音或手写)中的模式。搜索算法在模式识别中起着重要作用。它们帮助计算机将新数据与现有模式进行匹配,从而实现照片中的面部识别或虚拟助理的语音识别等应用。
算法类型:
1. Linear Search
:
想象一下,在一个杂乱无章的书架上寻找一本特定的书。线性搜索模仿了这种方法。它是一种简单的方法,逐一检查集合中的每个项目,直到找到目标元素(你想要的书)。
工作原理如下:
- 搜索从集合中的第一个项目开始。
- 该算法将目标元素与当前项目进行比较。
- 如果匹配,则搜索成功,算法返回目标元素的位置(索引)。
- 如果不匹配,算法将转到集合中的下一个项目。
- 这个比较和移动的过程一直持续到找到目标元素或整个集合被用尽。
例子:
让我们在未排序的列表中搜索值“25”:[10, 4, 12, 25, 18, 7]。
- 搜索从第一个元素(10)开始。由于 10 不等于 25,因此我们继续。
- 我们将目标 (25) 与下一个元素 (4) 进行比较。没有匹配,因此继续。
- 重复此过程,直到我们到达索引 3 处的元素“25”。搜索成功!
优势:
- 易于理解和实施,是初学者的不错选择。
- 处理未分类的数据,在各种情况下提供灵活性。
弱点:
- 对于大型数据集来说,搜索速度较慢。随着数据集规模的增长,搜索时间也会相应增加,因此对于海量数据集来说,搜索效率低下。
工作原理:
2. Binary Search
:
二分查找法适用于排序数据。想象一下,在一本精心组织的字典中搜索一个特定的单词。在这种情况下,二分查找法比线性查找法快得多。它的工作原理是反复将排序好的集合一分为二。其策略如下:
- 该算法首先将目标元素与集合的中间元素进行比较。
- 如果目标元素等于中间元素,则搜索成功,算法返回中间元素的索引。
- 如果目标元素小于中间元素,则继续在剩余集合的左半部分(不包括中间元素)上进行搜索。
- 如果目标元素大于中间元素,则继续在剩余集合的右半部分进行搜索。
- 在缩小范围的一半集合上重复步骤 1-4,直到找到目标元素或搜索空间缩小到单个元素(与目标不匹配)。
例子:
让我们在排序列表中搜索值“18”:[4, 7, 10, 12, 18, 25]。
- 中间元素是 12。由于 18 大于 12,因此我们关注右半部分:[18, 25]。
- 现在,右半部分的中间元素是 18。我们匹配成功了!目标元素位于索引 4 处。
优势:
- 对于大型排序数据集,二分查找的速度明显快于线性查找。通过在每次比较中消除一半的剩余元素,二分查找可以快速缩小搜索空间。
弱点:
- 需要预先对数据进行排序,如果数据尚未整理,则需要添加额外的步骤。
- 不适用于无序数据。二分查找策略依赖于数据的有序性,在每次迭代中有效地消除一半的可能性。
工作原理:
2.排序算法:
什么是排序?
排序是指根据元素的比较运算符对给定的数组或列表进行重新排列。比较运算符用于确定相应数据结构中元素的新顺序。排序是指对所有元素进行升序或降序重新排序。
介绍
在计算机科学中,排序算法是一种将列表中的元素按一定顺序排列的算法。最常用的顺序是数字顺序、字典顺序以及升序或降序。高效的排序对于优化其他需要输入数据处于有序列表的算法(例如搜索和合并算法)的效率至关重要。排序通常也有助于规范化数据并生成易于理解的输出。
形式上,任何排序算法的输出都必须满足两个条件:
输出是单调顺序的(根据所需的顺序,每个元素不小于/大于前一个元素)。
- 输出是输入的排列(重新排序,但保留所有原始元素)。
- 为了获得最佳效率,输入数据应存储在允许随机访问的数据结构中,而不是仅允许顺序访问的数据结构中。
摘要:排序算法是一组指令,它将数组或列表作为输入,并将其中的项目按特定顺序排列。排序通常采用数字或字母(或字典)顺序,可以按升序(AZ,0-9)或降序(ZA,9-0)排序。
术语:
- 就地排序:想象一下,在抽屉里重新整理衣服,但不需要把所有东西都拿出来。就地排序的工作原理类似。这些算法通过修改现有列表本身元素的顺序来对数据进行排序,从而最大限度地减少额外空间占用。示例包括选择排序、冒泡排序和插入排序。
- 内部排序:这指的是完全在计算机主内存 (RAM) 内运行的排序算法。整个数据集可以一次性加载到内存中,因此适用于中小型数据集。堆排序、冒泡排序和归并排序等内部排序算法通常用于内存数据操作。
- 外部排序:当处理超出主内存容量的海量数据集时,外部排序就派上用场了。这些算法将大型数据集分解成较小的块,在磁盘(二级存储)上对它们进行排序,然后按特定顺序将排序后的块合并在一起。合并排序是外部排序算法的一个常见示例。
- 稳定排序:假设您要按书名对一串书籍进行排序,但同时又希望保留同名书籍最初的排列顺序。稳定的排序算法会在排序过程中保持键(值)相等的元素的相对顺序。归并排序和插入排序就是稳定排序算法的例子。
- 不稳定排序:并非所有排序算法都优先考虑顺序保留。不稳定排序算法只关注实现所需的排序顺序(例如升序或降序),并且可能会打乱具有相同键的元素的相对位置。快速排序和堆排序就是不稳定排序算法的例子。
排序算法的特点:
-
时间复杂度:这指的是排序算法完成其工作所需的时间(以步骤或比较为单位)。我们通常在三种情况下分析时间复杂度:
- 最坏情况:考虑到最糟糕的输入情况,这表示算法处理特定数据大小所需的最长时间。
- 平均情况:这反映了算法处理相同大小的各种随机输入所需的平均时间。
- 最佳情况:考虑到最有利的输入场景(例如,数据已经部分排序),这表示算法处理特定数据大小所需的最短时间。
-
空间复杂度:这指的是排序算法在执行操作时,除了原始数据占用的空间之外,还需要多少额外的内存。就地排序算法通过在现有内存分配内操作数据,使用最少的额外空间,而某些算法在排序过程中可能需要额外的临时存储空间。
-
稳定性:此属性决定了排序算法是否在排序输出中保留值相等元素的原始顺序。稳定的排序算法会维护这些元素的相对位置,这在特定应用中可能非常重要。例如,如果您按姓名对客户记录列表进行排序,并且有两个客户姓名相同,则您可能需要稳定的排序来保持它们最初的排列顺序(例如,按帐户创建日期)。
-
就地排序:如前所述,就地排序算法内存效率高,因为它们通过修改原始列表本身来对数据进行排序,所需的额外空间极小。这在处理大型数据集或内存有限的情况下非常有利。
-
自适应性:某些排序算法能够根据其所排序数据的特性进行自适应调整。自适应排序算法可以利用数据中预先存在的顺序来提升其性能。例如,如果数据已经部分排序,自适应算法可能会调整其方法,利用该部分顺序来实现更快的排序。
排序算法的应用:
-
搜索算法:想象一下在电话簿中搜索特定联系人。排序算法是二分查找等高效搜索算法的默默伙伴。通过确保电话簿条目按字母顺序排列(排序),二分查找可以比在无序列表中进行线性搜索更快地找到您的联系人。
-
数据管理:数据是现代计算的命脉,但要有效地管理数据,就需要组织有序。排序算法在数据管理中起着至关重要的作用。按名称、日期或大小对文件列表进行排序,可以更轻松地找到所需的特定文件。此外,排序后的数据有助于更快地检索和分析,从而节省您的时间和精力。
-
数据库优化:数据库存储着海量信息,从客户记录到金融交易,无所不包。排序算法可以显著提升数据库查询的性能。当您在电商数据库中搜索特定商品时,数据库可能会根据您的搜索条件(例如价格)对商品列表进行排序,以便快速提供最相关的结果。
-
机器学习:机器学习算法从数据中学习,从而做出预测或分类。然而,为了有效地学习,数据需要预先准备。排序算法通常用于数据预处理步骤,在将数据输入机器学习模型之前对其进行组织和结构化。这可以显著提高学习过程的准确性和效率。
-
数据分析:数据分析的核心是从信息中提取洞察。排序算法在此过程中发挥着至关重要的作用。通过按各种属性(例如日期、位置、客户人口统计)对数据进行排序,您可以识别未排序数据集中可能不易察觉的模式、趋势和异常值。这使得数据分析师能够更深入地理解数据,从而为金融、市场营销和科研等各个领域的决策提供更完善的信息。
-
操作系统:操作系统管理计算机的资源。排序算法应用于各种操作系统任务。例如,排序算法可用于确定 CPU 任务的优先级、高效管理内存分配,或按目录结构组织文件,从而确保计算机系统的平稳运行。
这些只是排序算法如何渗透到我们日常生活中的几个例子。
简单解释:
假设你有一个凌乱的书架,上面摆满了各种主题的书籍。你想按类型对它们进行整理(排序)。以下是应用于此场景的排序算法背后的主要概念和逻辑:
- 比较:一次拿两本书,并根据它们的类型进行比较(就像比较列表中的两个元素一样)。
- 交换:如果书流的顺序不符合要求(例如,历史书放在小说之前),您可以交换它们在书架上的位置(就像重新排列列表中的元素一样)。
- 重复:您继续一次比较和交换两本书,直到所有书籍都按类型按所需顺序排列(列表中的所有元素都根据所选标准排序)。
排序算法::
1.冒泡排序
概念:冒泡排序是一种简单的排序算法,它遍历整个列表,反复比较相邻元素,如果顺序错误则交换它们。想象一下气泡上升到液体表面——每次循环,值较大的元素都会“冒泡”向上移动。这个过程一直持续到不需要交换元素,即列表已排序。
解释:
想象一下对一堆杂乱的玩具进行分类。冒泡排序的工作原理如下:
- 多次检查:您多次检查玩具清单。
- 比较相邻玩具:每次循环,你将每个玩具与其相邻的玩具进行比较。如果第一个玩具更大(或者用排序术语来说“更高”),就交换它们的位置。
- 气泡上升:随着每次交换,较大的玩具(如气泡)往往会移向列表的末尾。
- 继续直到无交换:在整个列表中重复这些比较和交换,直到完成所有操作且无需交换。这表示列表已排序。
时间复杂度:不幸的是,冒泡排序在最坏和平均情况下的时间复杂度均为 O(n^2)。这意味着排序时间会随着元素数量(n)的增加而呈二次方增长。对于大型数据集,冒泡排序的效率会变得非常低。
2.选择排序
概念:选择排序同样遍历列表,但不是直接比较相邻元素,而是着重于在未排序部分中找出最小元素(降序排列时为最大值)。然后,将该元素与未排序部分中的第一个元素交换,从而有效地将其置于正确的排序位置。该过程重复进行,每次循环都会逐步将未排序部分的位置减少一个位置。
解释:
想象一下,根据身高排列学生的照片。选择排序的工作原理如下:
- 找到最矮的(或最高的):在每次遍历中,您都会搜索队伍的整个未分类部分以找到最矮的学生(或按降序排列的最高的学生)。
- 与第一名交换:找到最矮的学生后,将其位置与未分类部分中的第一个学生交换,有效地将他们放在队伍开头的正确排序位置(最矮的在最前面)。
- 重复并减少未排序部分:继续此过程,将交换的元素视为已排序部分的开头,并在剩余的未排序部分中搜索最小元素。
时间复杂度:与冒泡排序类似,选择排序在平均和最坏情况下的时间复杂度也均为 O(n^2)。这意味着排序时间会随着元素数量的平方增长,因此对于大型数据集来说效率低下。
3.插入排序
概念:插入排序的工作原理是维护一个已排序的子列表,并迭代地将未排序部分的元素插入到子列表中的正确位置。想象一下,用积木搭建一座塔,但你只能逐个添加积木,并且希望保持塔按高度排序。插入排序就像在不断增长的排序塔中,策略性地将每个新积木放置在正确的位置。
解释:
想象一下,按照高度对书架上的书进行排序。插入排序的工作原理如下:
- 从单个排序元素开始:从一个空的排序子列表开始(就像书架上只有一本书)。
- 从未排序部分中取出一个元素:从未分类的书堆中挑选一本书。
- 移位并插入:从最右端开始,将新书与已排序子列表中的每本书进行比较。如果新书较短(或按降序排列时较长),则移动现有书籍以腾出空间,并将新书插入到正确的位置以保持排序。
- 重复并扩展已排序子列表:重复此过程,从未排序堆中取出元素,将其与已排序子列表进行比较,然后将其插入到正确的排序位置。此过程会逐渐扩展已排序子列表,直到所有元素都已合并。
时间复杂度:插入排序在部分排序数据中表现出色。对于已经部分排序的数据,平均时间复杂度为 O(n),效率较高。然而,对于完全随机的数据(最坏情况),时间复杂度可能会回落到 O(n^2),类似于冒泡排序和选择排序。
4. 归并排序
概念:归并排序采用一种巧妙的“分而治之”策略来高效地对列表进行排序。它将问题分解成更小、更易于处理的子问题,然后将这些解决方案按排序后的顺序重新组合在一起。
解释:
假设你有一支庞大的军队,需要按身高进行组织。归并排序的原理如下:
- 划分:将军队(列表)拆分成越来越小的组(子列表),直到每个组只有一个士兵(元素)。这就像把一个大问题分解成更小、更容易解决的部分。
- 征服:由于每个子列表现在只有一个士兵(元素),因此它已经被视为“已排序”。这是分治法的基本情况。
- 合并:现在到了合并部分。你需要策略性地将已排序的子列表重新组合在一起,但要采用特定的方式。你需要比较每个子列表中最前面的士兵(元素),并将较短的士兵(较小的元素)放入最终的排序列表中。你需要不断重复此比较和放置过程,直到两个子列表中的所有士兵(元素)都合并到最终的排序列表中。
- 重复:继续递归地应用这种分而治之和合并策略,直到整个原始军队(列表)按从最短到最高(从小到大)的顺序排序。
时间复杂度:归并排序的魅力在于其时间复杂度。在平均和最坏情况下,它的复杂度为 O(n log n)。这意味着对列表进行排序所需的时间会随着元素数量 (n) 的增加而呈对数增长,这比冒泡排序、选择排序或插入排序(其复杂度为 O(n^2))要快得多。
5.快速排序
概念:快速排序是另一种分而治之的排序算法,但方法不同。它依靠一个策略性选择的元素(称为“枢轴”)来划分列表并解决排序问题。
解释:
想象一下,你有一个书架,上面摆满了杂乱无章的书。快速排序的工作原理如下:
- 选择枢轴:从书架上选择一本书(枢轴)。枢轴的选择方式多种多样,但通常是列表中的第一个或最后一个元素。
- 分区:根据基准点重新排列书架上的书籍。类型字母顺序在基准点之前的书籍放在一侧,类型字母顺序在基准点之后的书籍放在另一侧。基准点本身尚未放置。这种分区有效地将较大的排序问题分成了两个较小的子问题。
- 递归征服:现在,你将两个子列表(一堆书)分别视为单独的排序问题。你以递归的方式将快速排序策略应用于这些子列表,为每个子列表选择一个新的枢轴,并相应地对它们进行划分。
- 合并:两个子列表都排序完成后,将原始枢轴元素放置在两个子列表之间正确的排序位置。现在,整个书架(列表)已按字母顺序排序。
时间复杂度:平均而言,快速排序的时间复杂度为 O(n log n),这使得它对于大型数据集非常高效。然而,其性能会因所选的枢轴元素而异。如果枢轴选择不当(例如,始终选择已排序或部分排序列表中的第一个或最后一个元素),则可能导致最坏情况的复杂度为 O(n^2),类似于冒泡排序、选择排序和插入排序。
3.树遍历算法:
什么是树遍历?
树形遍历是指探索树形数据结构的系统方法。它就像一张路线图,可以精确地访问街区(树)中的每一栋房子(节点)一次,确保不会迷路或重复访问同一栋房子。与可以直接按位置访问元素的简单数据结构不同,树形结构需要特定的算法来导航节点之间的连接。这些遍历算法定义了访问每个节点的顺序,允许你对节点包含的数据执行操作,例如搜索特定值、添加新节点或删除现有节点。遍历技术多种多样,每种技术都有其优势和应用场景,这使得树形遍历成为计算机科学中的一个基本概念。
介绍
树遍历,也称为树搜索,是在仅包含树边的图上执行的算法,每个节点只访问一次。此类算法仅在访问每个节点的顺序上有所不同。遍历树的两种经典方法是:广度优先搜索 (bfs),在进入下一级之前,先访问与根节点同级或距离根节点较远的节点;以及深度优先搜索,在进入下一个分支之前,先访问分支中的所有节点或从根节点到叶子节点的一条固定路径。还有其他方法使用启发式或随机采样来遍历树,以加快遍历过程。
概括:
- 目的:系统地探索树形数据结构,确保每个节点被访问一次。
- 优点:支持搜索特定数据、插入新节点或删除现有节点等操作。
- 主要区别:算法分为两种主要方法:
- 广度优先搜索 (BFS):逐级访问节点,从根开始向外推进。
- 深度优先搜索 (DFS):先尽可能深入地探索一条分支(路径),然后再回溯探索另一条分支。DFS 还针对特定应用提供了其他变体。
- 附加技术:其他方法利用启发式或随机采样来实现更快的遍历。
术语:
1. 树:一种分层数据结构,模拟一棵倒置的树,其中节点(数据点)通过边(链接)连接。节点可以有零个或多个子节点,形成分支,最终指向底部的叶节点(没有子节点)。
2. 节点:树的基本构建块,包含数据以及对其子节点的潜在引用。想象一下社区中的一栋房子——它保存着信息(数据),并通过道路(边)与其他房屋(子节点)相连。
3. 根节点:树的最顶端节点,作为遍历算法的起点。可以把它想象成街区的主屋,从那里开始探索。
4. 叶节点:没有子节点的节点,表示树中分支的“末端”。想象一下位于社区边缘的房屋,没有其他连接。
5. 边:树中两个节点之间的连接,描述它们之间的关系。想象一下连接附近房屋的道路。
6. 遍历:对树中的每个节点进行恰好一次的系统性访问过程。这就像探索整个街区,确保你走遍了每一栋房子,不会错过任何一栋,也不会重复访问同一栋房子。
7. 广度优先搜索 (BFS):一种逐层访问节点的遍历方法,从根节点开始向外扩展。想象一下,在探索街区时,先访问第一条街道(层)上的所有房屋,然后再移动到下一条街道(层)上的房屋。
8. 深度优先搜索 (DFS):一种遍历方法,先沿着一条分支(路径)尽可能远地探索,然后再回溯探索另一条分支。想象一下,沿着一条路(分支)探索邻域,直到到达死胡同(叶节点),然后回溯尝试另一条路。DFS 的常见变体包括前序、中序和后序,每种方法都具有访问分支内节点的特定顺序。
树遍历算法的特点:
1. 访问每个节点一次:
- 树遍历的核心原则是确保树中的每个节点仅被访问一次。这可以避免冗余处理,并确保对树结构进行完整的探索。
2. 探视顺序:
- 虽然每个节点只被访问一次,但树遍历算法的典型特征在于它们访问节点的顺序。不同的算法会优先按照特定的顺序探索节点,从而导致不同的遍历模式。
3.递归与迭代实现:
- 树遍历算法可以递归或迭代实现。递归方法涉及定义在子树上调用自身的函数,以模拟树的层次结构。迭代方法利用循环和堆栈来管理遍历过程。
4.时间和空间复杂度:
- 与任何算法一样,树遍历方法也具有相关的时间和空间复杂度。时间复杂度是指基于树中节点数 (n) 执行算法所需的时间。常见的复杂度包括 O(n)(线性)和 O(n log n)(对数),而 BFS 和 DFS 的变体根据实现方式具有不同的复杂度。空间复杂度反映了算法运行所需的额外内存量,通常取决于用于遍历的数据结构(例如堆栈)。
5.特定应用的选择:
- 树遍历算法的选择很大程度上取决于具体任务。例如,广度优先搜索 (BFS) 可能更适合用于查找树中两个节点之间的最短路径,而深度优先搜索 (DFS) 及其变体则可用于搜索特定数据或探索所有可能的路径。
6. 不修改:
- 一般来说,树遍历算法旨在探索现有的树结构,而不修改树本身。它们访问节点,对其包含的数据执行操作,但通常不会改变树中的连接或数据。
树遍历算法的应用:
1.文件系统导航:
- 操作系统使用树形遍历算法来导航计算机上的目录结构。想象一下,您的文件系统是一棵树,文件夹作为节点,子文件夹和文件作为子节点。广度优先搜索 (BFS) 可用于列出目录及其子目录中的所有文件,而深度优先搜索 (DFS) 可用于在层次结构中定位特定文件。
2.网络爬虫
- 像谷歌这样的搜索引擎会利用 BFS 或 DFS 的变体来抓取网页。它们从种子 URL(根节点)开始,系统地探索链接的网页(子节点)。BFS 确保在进入更深层次之前,先探索特定层级(网站)的所有页面;而 DFS 则会深入探索特定网站,然后再回溯探索其他网站。
3.人工智能(AI):
- 人工智能中的游戏算法通常使用树状遍历来探索可能的走法及其结果。想象一下,一局棋局就像一棵树,当前棋盘状态作为根节点,潜在走法作为通向新棋盘状态的分支(子节点)。深度优先搜索结合剪枝技术可以用来评估潜在走法并确定最有希望的策略。
4.社交网络分析:
- 社交媒体平台利用树状遍历来推荐联系人或探索好友网络。想象一下,您的个人资料是一个节点,而好友则是子节点。遍历算法可以根据共同好友(树中的共同祖先)推荐联系人,或探索网络以了解信息流或影响力。
5.计算机图形学:
- 光线追踪是一种用于在 3D 图形中实现逼真光照效果的技术,通常采用树状遍历算法。虚拟场景可以表示为一棵树,其中对象作为节点,其空间关系作为边。遍历有助于确定光线与哪些对象交互,从而创建逼真的阴影和反射。
6.网络路由:
- 计算机网络中的路由协议使用树形遍历的变体来寻找数据包到达目的地的最佳路径。将网络想象成一棵树,路由器作为节点,连接作为边。遍历算法有助于确定数据在网络中不同点之间传输的最有效路径。
简单解释:
想象一下,你是一名送货员,你需要在一个社区里派送一堆包裹。社区里的房屋通过道路连接,形成一个树状结构。
- 房屋就是节点:每栋房屋代表树中的一个节点,包含地址(数据)等信息,以及通过道路(边)连接的邻近房屋(子节点)的地址。
- 您的送货路线就是遍历:树遍历算法定义您访问每个房屋(节点)以递送包裹(对数据执行操作)的顺序。
有两种主要方式可以进行交付,它们对应于两种常见的树遍历方法:
1.广度优先搜索(BFS):像一个不断扩大的圆圈一样传递:
- 您从列表中的第一栋房子(根节点)开始。
- 您将包裹送到那所房子,然后在继续前进之前访问同一条街道(级别)上与其直接相连的所有房屋(邻居/子节点) 。
- 一旦您将货物送到了第一条街道(楼层)上的所有房屋,您就可以前往下一条街道(楼层)并重复该过程,在前往下一层之前先访问该楼层上的所有房屋。
这就像一个不断扩大的圆圈——从中心(根)开始,逐渐向外延伸,确保将包裹送达同一条街道(层)上的所有房屋后,再送达下一条街道。如果您想优先送达附近区域的所有房屋,这种方法非常有用,因为它们都位于同一街区,并且最小化行程时间至关重要。
2.深度优先搜索(DFS):深入研究一条街道:
- 您从列表中的第一栋房子(根节点)开始。
- 您将包裹送到那所房子,然后选择一条从那所房子出来的相连道路(分支)并沿着它一直走到尽头(叶节点),将包裹送到该路径(分支)上的所有房子,然后再回溯。
- 一旦到达该路的尽头(分支),您就会回溯到最后一个交叉路口(父节点)并选择另一条路(分支)进行探索,将货物送到该新路径上的所有房屋,直到到达另一个死胡同(叶节点)。
这就像探索迷宫——你选择一条路径(分支),沿着它一路走下去,沿途给居民送货,直到走到死胡同(叶子节点)。然后你回溯,尝试另一条路径(分支),直到到达所有居民。如果你想快速找到一个特定的地址,并希望先探索整条街道(分支),然后再前往另一条街道,这种方法会很有用。
算法类型:
1.广度优先搜索(BFS):
-
概念:广度优先遍历 (BFS) 逐级访问节点,从根节点开始,逐层向外推进。想象一下探索一棵家谱;广度优先遍历会访问所有兄弟节点(同一层级的节点),然后再向下移动到子节点(下一层级)。
-
工作原理:
- 从根节点开始并将其添加到队列(遵循“先进先出”原则的数据结构)。
- 从队列中移除第一个节点并访问它(处理其数据)。
- 将删除节点的所有未访问的子节点添加到队列的后面。
- 重复步骤2和3,直到队列为空。
-
例子:
考虑一棵简单的树:
A
/ \
B C
/ \ / \
D E F G
BFS 遍历将按以下顺序访问节点:A、B、C、D、E、F、G。
2.深度优先搜索(DFS):
-
概念: DFS 会沿着一条分支(路径)尽可能远地探索,然后回溯并探索另一条分支。DFS 还有其他变体,但这里我们将重点介绍一种基本方法。
-
工作原理:
- 从根节点开始。
- 访问节点(处理其数据)。
- 如果有任何未访问的子节点,请选择一个并重复步骤 2 和 3,基本上沿着该分支(路径)前进,直到到达叶节点(没有子节点的节点)。
- 一旦到达叶节点,就回溯到父节点并重复步骤 3,探索父节点的另一个未访问的子节点(如果有)。
- 继续回溯和探索,直到所有节点都被访问过。
-
例子:
使用与以前相同的树:
A
/ \
B C
/ \ / \
D E F G
DFS 遍历可以按照不同的顺序访问节点,具体取决于每一步选择哪个子节点。一个可能的顺序是:A、B、D、E、C、F、G。
主要区别:
- BFS 强调逐级访问节点,确保在深入探索之前进行更广泛的探索。
- DFS 优先彻底探索一个分支(路径),然后再转到另一个分支(路径),这样可能会更快地到达特定节点,但不能保证逐级访问。
结论 :
总而言之,这段基础算法之旅为你理解基本的搜索、排序和树形遍历技术奠定了坚实的基础。讲解运用清晰的语言和通俗易懂的类比,使这些抽象概念更加通俗易懂、直观易懂。无论你是经验丰富的程序员,还是刚刚踏入计算机科学领域,这些理解都将为你构建高效程序奠定坚实的基础。
随着你对知识的渴求与日俱增,不妨进一步深入探索!我的代码库 ( algorithms-data-structures )汇聚了各种算法和数据结构,等待你的探索。这里就像一座宝库,你可以在这里进行实验、练习,巩固对这些基本构建模块的掌握。
虽然有些部分仍在建设中,反映了我自己正在进行的学习历程(这段历程可能需要 2-3 年才能完成!),但存储库也在不断发展。
冒险不止于探索!我非常重视您的反馈。在文章中遇到难题?有建设性的批评意见要分享?或者只是想开启关于算法的讨论?我的大门(或者更确切地说,我的收件箱)始终敞开。欢迎通过 Twitter:@m_ mdy _m或 Telegram:@m_mdy_m 联系我。此外,我的 GitHub 帐户m-mdy-m欢迎大家讨论和贡献。让我们共同构建一个充满活力的学习社区,分享知识,突破理解的界限。
文章来源:https://dev.to/m__mdy__m/basic-algorithms-5bep