我对于算法的理解

  我个人曾经在大二的时候读过《算法导论》这本书,虽然我在之后的学习中很少再看这本书了,但是《算法导论》带给我的启蒙意义远超过其他我看到过的书籍,哪怕是如今研究一些比较深入的程序语言理论,也少有书籍能做到《算法导论》对我个人的影响,我认为唯一可以媲美它的就是Dan Friedman的《the little schemer》,关于《the little schemer》的内容我以后会讲,但是无论你是不是函数式编程的爱好者,我都推荐你来看《the little schemer》。

  为什么讲《算法导论》对于我个人有如此之大的影响呢?我认为是它彻底改变了我对于写代码这件事的认识,以及写代码的方式的改变。

  它让我认识到代码是可以证明其正确性的。

  用在证明代码正确性的思想有两点,一个是分类讨论,另一个是数学归纳法,而其中的关键就是通过将情况的划归,和缩小问题的大小去构造子问题,再通过假设子问题的成立,构造关于当前问题的证明,从而证明函数的正确性,一个很好的类比就是数学归纳法,我们首先证明i=1时成立(基本情况成立),然后假设i=n-1时成立(构造子问题成立),证明i=n时成立(证明函数成立)。

  我用一个红黑树插入的例子来说明我的思想。

  首先红黑树的插入是进行一个与平衡二叉树插入同样的操作,然后将新插入的节点赋为红色,赋为红色的意义是确保插入该节点后,不会破坏该节点所在子树的黑高度,从而使破坏的性质只为其父节点为红色,保证只有这个性质被破坏了。

  然后进行的是对红黑树被破坏性质的修补工作,首先我们知道的是只有在其父节点为红色时,红黑树性质才有被破坏的可能性,而父节点为红色,那么爷爷节点只可能为黑色,不确定的是父节点的兄弟节点(我把它叫做叔叔节点)的颜色,以及插入子节点(我把它叫做孙子节点)的位置(是父节点的左子节点还是右子节点)。

  我们现在使用分类讨论的思想:

  情况 1:叔叔节点为红色,这样我们可以把爷爷节点的黑色传递给父亲节点和叔叔节点,这样修补了在孙子节点处发生的冲突,同时保持了爷爷节点处所在子树黑高度不变,然而爷爷节点变为红色,爷爷节点处可能与太爷爷节点处的红色发生冲突,问题转移到爷爷节点处。

  在情况1中最后就是把问题进行了缩小,原先要处理孙子节点以上的红黑树冲突,现在只需要处理爷爷节点以上的冲突了。

  情况2:叔叔节点为黑色,这时候我们首先要考虑孙子节点是父节点的左子节点还是右子节点,现在我们假设是右节点,这样我们对父节点进行一个左旋操作,这样父节点变为孙子节点,孙子节点变为父节点,实际上此时孙子节点为父节点的左子节点,该情况被我们转化为情况3.

  在情况2中我们使用的思想是通过将一种情况转移为另一种情况,来减少情况。

  情况3:叔叔节点为黑色,孙子节点为父节点左子节点,这时,我们把爷爷节点的黑色与父节点的红色调换,这样父节点所在子树黑高度比叔叔节点所在黑高度多1,我们对爷爷节点使用一个右旋操作,这样父节点黑高度减1,叔叔节点黑高度不变,红黑性质修复完成。

  这里只是举了红黑树插入操作的例子来说明算法证明,实际上算法导论中大部分算法都可以用这几个简单的想法(分类讨论,情况转移,数学归纳证明)进行解释和证明。

时间: 2024-10-16 04:42:57

我对于算法的理解的相关文章

POJ1523(求连用分量数目,tarjan算法原理理解)

SPF Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 7406   Accepted: 3363 Description Consider the two networks shown below. Assuming that data moves around these networks only between directly connected nodes on a peer-to-peer basis, a

01背包算法的理解

01背包问题: 有N件物品和一个最大重量限制为V的背包.第i件物品的重量是c[i],价值是w[i].求解将哪些物品装入背包可使这些物品的重量总和不超过V,且价值总和最大.每个物品只有1份,且不可分割 看了01背包算法,言简意赅,但理解起来头昏脑胀,不得要领.尝试解释下对该算法的理解,加深记忆. 假设最优解已经存在,怎么判断一个物品i是否在背包里?  简单,只要知道, 1.c[i]是否大于V, 2.F[i-1][V-c[i]],即没有i物品的情况下,最大重量限制为V-c[i]的最优解. 3.F[i

【转】浅谈对主成分分析(PCA)算法的理解

以前对PCA算法有过一段时间的研究,但没整理成文章,最近项目又打算用到PCA算法,故趁热打铁整理下PCA算法的知识.本文观点旨在抛砖引玉,不是权威,更不能尽信,只是本人的一点体会. 主成分分析(PCA)是多元统计分析中用来分析数据的一种方法,它是用一种较少数量的特征对样本进行描述以达到降低特征空间维数的方法,它的本质实际上是K-L变换.PCA方法最著名的应用应该是在人脸识别中特征提取及数据维,我们知道输入200*200大小的人脸图像,单单提取它的灰度值作为原始特征,则这个原始特征将达到40000

KPM算法初步理解

一个字符串"FBCABCDABABCDABCDABYW"中是否包含另外一个字符串"ABCDABY"? 上面这道题目是一个经典的字符串匹配的题目,对于字符串匹配,比较好的算法里很容易想到KPM算法,那KPM算法是干什么的?为什么说KPM比较优秀? 给定一个字符串O和F,长度分别是m.n,判断F是否在O中出现,如果出现则返回出现的位置.常规方法是遍历O的每一个字符,与F的每一个字符进行比较,但是这种方法的时间复杂度是T(m*n),但是KPM算法使得时间复杂度为T(m+n

对动态规划算法的理解及相关题目分析

1.对动态规划算法的理解 (1)基本思想: 动态规划算法的基本思想与分治法类似:将待求解的问题分解成若干个子问题,先求解子问题,然后从这些子问题的解中得到原问题的解.但是,与分治法不同的是,为了避免重复多次计算子问题,动态规划算法用一个表记录所有已解决的子问题的答案,不管该子问题以后是否被利用,只要它被计算过,就将其结果填入表中. (2)设计动态规划算法的步骤: ①找出最优解的性质,并刻画其结构特征 ②递归地定义最优值 ③以自底向上的方式计算最优值 ④根据计算最优值时得到的信息构造最优解 (3)

KMP算法详细理解

KMP算法详细理解 从昨天开始看KMP算法到今天凌晨..... 把一些知识点进行总结,其实KMP还是挺简单的(HHHHHH) 博客新地址:https://miraitowa2.top/ 1:BF(暴力匹配)算法 假设现在我们面临这样一个问题:有一个文本串S,和一个模式串P,现在要查找P在S中的位置,怎么查找呢? 如果用暴力匹配的思路,并假设现在文本串S匹配到 i 位置,模式串P匹配到 j 位置,则有: 如果当前字符匹配成功(即S[i] == P[j]),则i++,j++,继续匹配下一个字符: 如

对回溯算法的理解

一.对回溯算法的理解 应用回溯算法的三个步骤: 1.首先得构造解空间树:子集树和排列树: 2.以深度优先的方式搜索解空间:递归或迭代: 3.设计剪枝函数避免无效搜索:使用约束函数,剪去不满足约束条件的路径或使用限界函数,剪去不能得到最优解的路径. 回溯法解问题的一个显著特征是,解空间树是虚拟的,在任何时候,只需保存从根节点到当前扩展结点的路径. 在回溯问题中,若要求问题的所有解,就要回溯到根. 二.请说明“子集和”问题的解空间结构和约束函数 子集和问题: 设集合S={x1,x2,…,xn}是一个

二分算法 再次理解

二分算法 再次理解 详解二分查找算法 这篇博客很详细介绍了二分算法的一些细节问题 寻找一个数,也是最基本的二分搜索 //代码示例如下 int bsearch(int []nums, int target) { int left=0, right=nums.length-1;//这里的数组长度用法可以是其他的形式 while(left<=right) { int mid = left + (right - left) / 2; if(num[mid] == target) return mid;

KMP算法的理解

---恢复内容开始--- 在看数据结构的串的讲解的时候,讲到了KMP算法——一个经典的字符串匹配的算法,具体背景自行百度之,是一个很牛的图灵奖得主和他的学生提出的. 一开始看算法的时候很困惑,但是算法思想很简单,就是在暴力匹配的基础上得出的. 暴力匹配 这里有必要说一下暴力匹配,暴力匹配更简单,就是按照人的常规思维去匹配字符串,拿模式串(P)的第一个字符去和给定串(S)比较,S从左往右看,一看,第一个,呀~不对,啥也不说了,第一个都不对了,后边还比个毛.所以,这一次比较,S中第一个字符开头是匹配

deep learning 自编码算法详细理解与代码实现(超详细)

在有监督学习中,训练样本是有类别标签的.现在假设我们只有一个没有带类别标签的训练样本集合 ,其中 .自编码神经网络是一种无监督学习算法,它使用了反向传播算法,并让目标值等于输入值,比如 .下图是一个自编码神经网络的示例.通过训练,我们使输出 接近于输入 .当我们为自编码神经网络加入某些限制,比如限定隐藏神经元的数量,我们就可以从输入数据中发现一些有趣的结构.举例来说,假设某个自编码神经网络的输入 是一张 张8*8 图像(共64个像素)的像素灰度值,于是 n=64,其隐藏层 中有25个隐藏神经元.