热门标签 | HotTags
当前位置:  开发笔记 > 人工智能 > 正文

你必须背下的几个经典算法[2nd]

(三)红黑树红黑树自身具有优秀的平衡性,具有很高效的检索速度,很适于对有权重的数据进行组织和查找。红黑树首先是一种二叉搜索树,因而具有“左下最

(三) 红黑树 红黑树 自身具有优秀的平衡性,具有很高效的检索速度,很适于对有权重的数据进行组织和查找。红黑树首先是一种二叉搜索树,因而具有“左下最

(三)红黑树

红黑树自身具有优秀的平衡性,具有很高效的检索速度,很适于对有权重的数据进行组织和查找。红黑树首先是一种二叉搜索树,因而具有“左下最小、右下最大”的性质。红黑树的每个节点(node)至少包括了5个域: 父节点指针、左孩子指针、右孩子指针、关键字、颜色,红黑树具有如下特性,才使得它具有如此优秀的性质:

[1]红黑树的节点要么是黑色,要么是红色。
[2]根节点是黑色
[3]叶子节点是黑色(根节点和叶子节点一般用一个唯一的域值为null的null节点表示)
[4]红色节点的孩子必须是黑色
[5]从任意节点到达叶子节点,所经过的黑色节点数目相等
(其中黑高可以用来特指某个节点到达它的叶子节点的路径上黑色节点数目,不包括其自身)
一个红黑树的建树时间是O(n*lg(n)),插入时间是O(lg(n)),删除时间是O(lg(n)),检索时间是O(lg(n))。
二叉搜索树的旋转操作:
X
/ \
a Y
/ \
b r
旋转为:
Y
/ \
X r
/ \
a b


不需要额外的指针就能进行旋转操作,步骤如下
[1] y = x.right 这里用到了两个指针,包括一个参数
[2] x.p.left_or_right = y; y.p = x.p;
[3] x.right = y.left; y.left.p = x;
[3] y.left = x; x.p = y;
红黑树的插入:
步骤一: 根据二叉搜索树的方法插入节点并且标记为红色,不考虑节点插入对4个性质的违背
步骤二: 由于可能违背了性质2、(非根)必须违背性质4,进行着色调整。调用RB-INSERT-FIXUP,分三种情况进行处理:
(1)叔节点为红色,自身为左孩子或者右孩子均可
(2)叔节点为黑色,自身为左孩子
(3)叔节点为黑色,自身为右孩子


(1)将祖父节点的黑色变为红色,将黑色分给父节点和叔节点,继续针对祖父节点递归,这样黑高向下“移”而不变,而且操作仅仅使着色发生变化

(2)对父节点进行右旋操作,并且保持树的颜色分布,这样颜色分布不变,仅仅是父节点进行了右旋


(四)基数排序

基数排序的思想是将n个待排元素对应到一个多位的整数,一共有d位,每一位都可以取值k个值; 对每一位为标准位进行一次稳定的排序,整个元素的顺序按照这个标准位进行排列,继续从低位排序到高位,并对这个元素重新排序; 如果每一次稳定排序的时间是O(n+k),那么最终时间是O(d*(n+k))。


(五)桶排序

桶排序是针对在一定区间内均匀分布(或近似于均匀分布)的数据进行排序的,所以是一种特殊(非普适)的算法。我们假设分布的区间是[0, 1),对这个长度为1的区间分成n个小区间(我们称之为桶),每个区间长度为1/n,每一个小区间对应一个链表,当新数据输入时,我们将输入数据逐个地和桶的标准分界值比较,当输入数据落入某个区间时,将它插入到对应的链表中去,在插入的时候又可以进行比较从而使得链表内数据有序。当所有输入完成后,将所有链表(除了头节点)链接起来,形成一个总的链表。

(六)动态规划

算法基本思想是分治:将问题分解为若干个子问题,但是要进行中间结果(即子问题的解)的记录,在继续计算时,会多次使用前面的中间结果,将这些子问题的解有序地组合起来,一般可以组成一个二维数组,备存便用,这成为了动态规划的最大特征。可见动态规划是一种牺牲空间换取时间为代价的,中间结果放在存储表中。利用这种思想对递归方法进行改进得到了记忆型递归,即每次递归到子问题时先查询是否有中间解,没有继续递归,否则直接使用已得结果,如矩阵链乘法。

动态规划的使用还有一个重要的原则:即子问题的原问题的最优解的必要条件,即如果最终的解是最优的,那么解的每一个细分(按照子问题划分)或每一个步骤都是最优的。比如最短路径问题,它的子步骤是到达终点的路径分段,即包含终点的子路径的选择(从后向前),要确保每一个字分段都是最优的。即如果是最优的,则有是最优的。这里0-1背包问题和最短路径问题都是最优解问题。

(七)0-1背包问题

算法的思想简单,是基本的递归思路,只不过在每一层递归时,考虑下一个物品的取舍,以及下一物品是否“超重”,总是遵循“累计”价值最大以及“超重不取”的原则,而不是“能装则取”。

不过在构造存储表时需要更多的技巧,这是一个矩阵(二维数组),i下标代表剩余的物品数,j下标代表剩余的容量。由于二维数组下标是连续变化的,所以对每一个单位的剩余重量都要分配存储空间和初始化&#20540;,这里考虑的临界条件比较巧妙,对数组元素赋的初&#20540;经过了精心设计:a.对于取最后一个物品的,即剩余n个物品的初&#20540;,假设W[n] <= C,即能装的下最后一个物品(最后一个指的是第n个而不是时间上的概念),则映射到这个冗余的存储数组时,从M[n][W[n]]到M[n][C]都要赋一样的初&#20540;,因为这时只能取一个物品n,并且取完之后使得M[n][.](.代表上述范围内的&#20540;)是,考虑了第n个物品的取舍之后的,所能取得物品的最大价&#20540;,即M[n][W[n]...C] = W[n],;这里进一步考虑对于第n个物品,元素下标j为0到W[n]-1的情况,虽然在目前看来不可能,因为我们的物品n重量W[n]M[n][0...W[n]-1] = 0,即不能选取物品,考虑物品n后,总的最大的价&#20540;是0。b.如果W[n]>C,装不下最后一个物品,对于则只能对这些&#20540;赋0,即考虑第n个物品的取舍之后,得到的总的最大价&#20540;仍然是0,也就是M[n][0...C] = 0。归纳以上两种情况,令MaxJ = min(W[n] - 1, C),有M[n][0...MaxJ] = 0; M[n][W[n]...C] = W[n]; (注意:这里W[n]...C在遇到W[n] > C的情况时,认为赋&#20540;不会被执行)

重复以上思路,对于0...C(...表“到”)即全部的重量范围,无论还剩余多少个n-1以内的物品,都无法估算出,考虑了这些物品后,能够获得的最大价&#20540;;因为在考虑这些物品时,至少还要考虑对是否选择第n个物品,由此产生的最大价&#20540;的比较问题(第n个物品有可能选有可能在装不下时不选),从而无法赋初&#20540;。其中又可以分为两种情况:a.W[i] <= C,可以放得下第i个物品,这时与第n个物品的取舍不同,要考虑取还是不取第i件物品,因为这直接影响到在子问题的解当中做的选择,所以有 M[i][j] = max(M[i&#43;1][j-W[i]] &#43; V[i], M[i&#43;1][j]),j = W[i]...C; M[i][j] = M[i&#43;1][j],j = 0...W[i]-1(这里考虑到为了提供剩余容量在选择下一个物品后可能会受到限制,而存储的可供选择的数&#20540;,即物品i没有被选择时容量不变)。b.W[i] > C,放不下物品i,M[i][j] = M[i&#43;1][j],j = 0...C。归纳来说,就是MaxJ = min(W[i] - 1, C),有M[i][j] = M[i&#43;1][j],j = 0...MaxJ;M[i][j] = max(M[i&#43;1][j-W[i]] &#43; V[i], M[i&#43;1][j]),j = W[i]...C。

在这里,又有一个细节性的关键问题,在这个算法中,取第i件物品影响的不是还没有的取得物品,而是自身的问题最大价&#20540;,这里要考虑的是选取物品i使得剩余空间减少的情况下子问题的最大&#20540; 和 不选取物品i的剩余空间下子问题的最大&#20540;,而不是第i&#43;1件物品已经确定,剩余容量大小和i的增减之间也没有正相关的关系,只是第i&#43;1件物品的子问题提供了在不同剩余空间下最大价&#20540;的子问题解的选择而已;具体地说,这里用到的反向思维方式,即我们的问题的最优解取决于子问题的最优解,而子问题的最优解是已经解决的问题的解和当前考虑的新元素对应的情况处理组合,而不是仅仅是在子问题解中选择最大价&#20540;的解,这里我们要在i&#43;1物品的考虑点上,对两个不同的剩余容量存储&#20540;对应的价&#20540;之间进行选择,即选择采用M[i&#43;1][j]还是M[i&#43;1][j-W[i]]。这有悖于正常思维,因为我们可能认为第i&#43;1个物品已经选过,而对它的选择取还是不取,考虑时剩余的背包容量空间应该固定的,而这里却受到第i个物品的取舍的影响。这里,正是这个算法的精髓所在,即在考虑某个物品时,要考虑所有的容量空间,在这些容量空间下,取舍该物品所能得到的总的价&#20540;都要计算。 这样,在选取之后的第i件物品时,第i件物品的取舍直接影响到对于第i&#43;1个子问题解的选择范围,这里的选择范围是取或不取第i件物品造成的剩余容量的限制,具体地说,就是选取第i件物品时在剩余容量下取最大价&#20540;的子问题的解,和在不取第i件物品时在剩余容量下取最大价&#20540;的子问题的解,在这基础上再考虑第i件物品的选取带来的价&#20540;,由此作出选择。

用数学表达式表示如下:


推荐阅读
  • 我的读书清单(持续更新)201705311.《一千零一夜》2006(四五年级)2.《中华上下五千年》2008(初一)3.《鲁滨孙漂流记》2008(初二)4.《钢铁是怎样炼成的》20 ... [详细]
  • MySQL InnoDB 存储引擎索引机制详解
    本文深入探讨了MySQL InnoDB存储引擎中的索引技术,包括索引的基本概念、数据结构与算法、B+树的特性及其在数据库中的应用,以及索引优化策略。 ... [详细]
  • 使用 MATLAB 将高光谱数据集转换为伪彩色 CIE 图像
    本文介绍了一种方法,通过 MATLAB 将高光谱数据集的每个维度的图像转换为伪彩色 CIE 图像。用户只需指定波段即可完成转换。 ... [详细]
  • 本文总结了一次针对大厂Java研发岗位的面试经历,探讨了面试中常见的问题及其背后的原因,并分享了一些实用的面试准备资料。 ... [详细]
  • Windows操作系统提供了Encrypting File System (EFS)作为内置的数据加密工具,特别适用于对NTFS分区上的文件和文件夹进行加密处理。本文将详细介绍如何使用EFS加密文件夹,以及加密过程中的注意事项。 ... [详细]
  • 深入解析WebP图片格式及其应用
    随着互联网技术的发展,无论是PC端还是移动端,图片数据流量占据了很大比重。尤其在高分辨率屏幕普及的背景下,如何在保证图片质量的同时减少文件大小,成为了亟待解决的问题。本文将详细介绍Google推出的WebP图片格式,探讨其在实际项目中的应用及优化策略。 ... [详细]
  • 菜鸟物流用户增长部现正大规模招聘P6及以上级别的JAVA工程师,提供年后入职选项。 ... [详细]
  • 深入解析层次聚类算法
    本文详细介绍了层次聚类算法的基本原理,包括其通过构建层次结构来分类样本的特点,以及自底向上(凝聚)和自顶向下(分裂)两种主要的聚类策略。文章还探讨了不同距离度量方法对聚类效果的影响,并提供了具体的参数设置指导。 ... [详细]
  • QQ推出新功能:个性化QID身份卡
    您是否还记得曾经风靡一时的即时通讯工具QQ?近日,QQ悄然上线了一项新功能——QID身份卡。这项功能将如何改变用户的社交体验?本文为您详细解读。 ... [详细]
  • 本文详细介绍了如何在ARM架构的目标设备上部署SSH服务端,包括必要的软件包下载、交叉编译过程以及最终的服务配置与测试。适合嵌入式开发人员和系统集成工程师参考。 ... [详细]
  • Bootstrap Paginator 分页插件详解与应用
    本文深入探讨了Bootstrap Paginator这款流行的JavaScript分页插件,提供了详细的使用指南和示例代码,旨在帮助开发者更好地理解和利用该工具进行高效的数据展示。 ... [详细]
  • 深入理解云计算与大数据技术
    本文详细探讨了云计算与大数据技术的关键知识点,包括大数据处理平台、社会网络大数据、城市大数据、工业大数据、教育大数据、数据开放与共享的应用,以及搜索引擎与Web挖掘、推荐技术的研究及应用。文章还涵盖了云计算的基础概念、特点和服务类型分类。 ... [详细]
  • 八段代码完全控制Promise
    1.Promise的马上实行性varpnewPromise(function(resolve,reject){console.log(createapromise);resolve ... [详细]
  • c语言二元插值,二维线性插值c语言
    c语言二元插值,二维线性插值c语言 ... [详细]
  • 计算机学报精选论文概览(2020-2022)
    本文汇总了2020年至2022年间《计算机学报》上发表的若干重要论文,旨在为即将投稿的研究者提供参考。 ... [详细]
author-avatar
飘雪2502923303
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有