摘要:更正一下前面一篇博文中的不妥之处:前面一篇博文有非无向图而不可广度优先遍历之嫌。其实广度优先搜索也是可以用在有向图中的,因为无向图是特殊的有向图,而这里广度优先遍历为的是遍历连通图的所有节点,对于有向图来说只要存在一条有向边,那么两个节点就是“连接”的状态,那么遍历就可以缠绕在这条边上。 深度优先遍历,也就是尽量深的遍历图的节点,同样用到了三色标记,用到了递归函数,这里还有一个盖时间戳的操作。当发现某个节点时记录一下时间,当完成一个节点的遍历时记录一下时间,这样依据时间戳,可以发现很多性质和应用。 其实在很多地方广度优先搜索和深度优先搜索代码实现起来都有特点:广度优先搜索使用一个queue来.
阅读全文
摘要:图的广度优先算法是图的基本算法,也是最小生成树以及单源最短路径算法的基础。最近把广度优先遍历算法实现了一下,希望能够有比以前更深的体会或者加强一下对该算法的理解。前些天看了优米网上关于于丹做客在路上的一段视频,有一点心得体会。我很赞同于丹的观点,一个人的见识是十分重要的,所谓见识,从某一方面来理解,那就是要亲历亲为。对于算法这一门数学与编程并重的学科更是如此。 任何一种算法,都需要搞清楚该算法的上下文环境,你需要问自己一些问题,这个算法叫什么名字,解决的是那一类问题,这些问题的重要定义或者条件是什么。其实没有什么万能的方法,但是确实存在能够解决一些特定条件集下的特定问题的算法。这里的广度优先.
阅读全文
摘要:基数排序是一种有趣的算法,有一点逆向思维的冲突在里面。下面举一个例子:如果要对5个3位整数进行排序,你会怎么做?我猜想大多数人会这样做(根据我们学习过的的数学中的一些概念惯性): 123 123 123 343 135 135362 241 241241 343 343135 362 362先对高位进行排序,然后对高位相同的,次高位进行排序,一直进行到低位。基数排序进行排序的方向和我们通常思考的方向相反,也就是说从低位开始往高位排序,为什么也能得到正确的结果呢?这里用到了数学里的归纳法,或者说是计算机科学里的递推法,由于这是一个递归的过程,试想对低1位排好序之后,低1位是有序的,接着对第2位进
阅读全文
摘要:计数排序的中间目标和快速排序的中间目标是一致的,都是需要找到一个元素在最终排好序的数组中的位置。快速排序使用了一种优雅的Partition技术,而计数排序如同它的名字描述的一样,进行计数得到最终位置。试想一下如果知道一个元素前面的元素个数,那么也就是知道了该元素在最终数组中的位置了,为了得到元素之前的元素个数,对于计数排序做了如下限定:待排序数组A的大小为n,而A中的元素的值在0-k之间,如果k = O(n)那么这种情况下比较时候使用计数排序。使用一个C[1...k]的数组,用于统计1..k这k个值出现的次数,然后前后相加就可以得到小于等于某一个元素的元素个数了,这个时候需要稍微考虑一下如果存
阅读全文
摘要:快速排序是一种十分优雅和十分实际有效的算法。快速排序和归并排序一样,也是一种用递归的算法。归并排序的基本递归操作是合并两个已经排好序的数组,而快速排序的基本递归操作是Partition,当然这个也是快速排序算法的核心,输入一个未排序的数组,选择其中一个元素,如何将它插入到数组中的某个位置,使得这个位置之前的所有元素都小于这个插入的元素,这个位置之后的元素都大于这个待插入的元素,简单来说,把待插入的元素放在排好序之后期望的正确位置上。快速排序算法的划分,也就是Partition使用了交换和一个优雅的扫描模型:使用两个游标i,jA[0...i]表示小于x的元素,[i+1...j-1]表示大于x的元
阅读全文
摘要:堆排序是基于堆这样一种数据结构的排序算法。下面简单介绍一下堆,在数据结构的范畴里,堆是一种完全二叉树的数据结构,满足任何一个父节点都大于其子节点(大根堆)或者任何一个父节点都小于其子节点(小根堆),所以堆有两个要素:1.堆是一颗完全二叉树,2.其父子的大小关系。逻辑上的概念比较简单,即以上的两个要素,那么在实际存储堆的时候会有一些小技巧的出现,其实在逻辑概念转化为实际的存储表示时总是存在这样的转化技巧。堆可以用一个抛弃0位不用的数组来表示,这种表示基于完全二叉树的一些性质:1. parent(i) = i/2 2.left(i) = i*23.right(i) = i*2 + 1以上的三个性质
阅读全文
摘要:本文针对的读者:了解递归,期望加深对归并排序的理解或者第一次接触归并排序归并排序,前一篇我们讲了插入排序,插入排序之所以叫做插入排序,是因为其复杂度最高的地方在插入的部分,为什么复杂度高?前面一篇已经比较详细的阐述了,因为插入出想的情况有三种,而人脑将三种情况统一在一块代码上,就显得有点困难了。如果是统一在一个概念之下会比较简单。那么这里的归并排序,所谓“归并”,“归”是递归,也就是说这个算法是一个递归的算法,大部分递归的算法都相对来说有容易想的优点,“并”是该算法的核心,也就是说复杂度就在这里了,如何将两个已排好的序列合并成一个排好的序列?这个比较简单,但是在实际编程的时候需要一个小技巧。下
阅读全文
摘要:本文针对的读者: 熟悉C++语法,期望进一步加深对插入排序的理解或者第一次接触插入排序的同学插入排序的思路和平时人们在打扑克牌时整理手中的牌的思路是完全一致的。 下面举一个实际的例子:在C++中,假设有一个int型的数组中存了未排序的一组数,如何采用插入排序的方法进行排序?仔细的回想一下整理扑克牌时的过程,刚开始手中没有牌,然后从牌堆拿一张牌,这时候手里有一张牌,当然此时手里的牌是有序的,继续从牌堆里拿牌,然后插入到手中的适当的位置,使手中的牌有序,接着继续从牌堆拿牌,并且插入手中,当牌堆中的牌拿完了之后,手中的牌也是排好序的,这样就完成了插入排序。从上面描述的过程中可以看出,这里有一个一直在
阅读全文
摘要:这一道题在poj上的AC ratio很低,客观上是因为这道题的细节较多,特别是在输出格式上的细节。在discuss中,我看到有一些人贴出代码,这个做法我不赞同,不管怎么 样,如果只是不加深入研究的复制粘贴AC,那也没有任何意义。给出一些测试数据帮助思考,我还是比较赞同的。 算法是一个半数学半工程的学科,所以它首先是严谨的,另外它又有别于数学更加贴近实际的问题。算法解决问题,不单纯依赖数学,生活实际中的问题有一些更注重策略和解决方案,而非数学。 希望以上的代码和叙述能给后来者一些有用的提示,切忌直接拷贝代码哦,如果能帮到你,我会很惊喜。#include <cstdio>#includ
阅读全文