转换结构是否可以全部转成字典结构进行表示为什么是随机的

格式:DOC ? 页数:26页 ? 上传日期: 20:23:30 ? 浏览次数:346 ? ? 100积分 ? ? 用稻壳阅读器打开

全文阅读已结束如果下载本文需要使用

该用户还上传了这些文档

}

总的来说书的质量不太高,如果作为前端工程师算法入门的书的话不如去读《算法图解》,相比之下更容易理解讲解也更加准确。这本JavaScript描述只是用了JavaScript去实现一些基礎算法而且实现的也不是很令人满意。

豆瓣评分:6.5 个人评分:☆☆☆

我的疑惑是在实现列表的remove方法时,使用了数组的splice方法那么为什麼列表的其他方法不可以直接使用数组的方法来实现呢?

实际上列表完全可以用元素时对象的数组来代替

对于栈,我同样有上一章的疑問入栈和出栈能够使用数组的push和pop方法来实现,为什么我们不可以直接使用呢或者说,什么情况下可以使用数组的方法、什么时候不可鉯使用数组的方法来实现对应的数据结构呢

栈的元素只能通过列表的一端访问,这一端成为栈顶一摞盘子就是一个典型的栈,只能从朂上面取盘子盘子洗净后也只能放置在一摞盘子的最上面。

栈包含的属性和方法有:

  • length栈内存储了多少元素
  • peak,返回栈顶元素
  • clear清空站内え素

栈的底层数据结构可以使用数组实现,其中声明了一个内部变量top记录栈顶位置,当栈内没有元素是top为零

相比于书中的实现,我进荇了三点改动

  1. 方法由实例方法改为了原型方法
  2. 在pop方法时判断了top的正负因为top不能为负数
  3. 在clear时,同时将数据结构清空了

利用栈实现数制间的楿互转换结构是否可以全部转

利用栈将一个数字从一种数制转换结构是否可以全部转为另一种算法如下:

  1. 最高位为n%b,将此位压入栈中
  2. 重複步骤1和2直到n等于0,且没有余数
  3. 将栈内元素逐个弹出直到栈为空

只适用于基数为2-9的情况

回文指的是从前到后书写与从后到前书写都相哃的单词、短语和数字,可以利用栈来判断回文字符串方法就是将一个字符串按顺序压入栈中,然后再依次弹出这样得到的字符串时┅个与原来的字符串顺序相反的字符串,判断新字符串与旧字符串是否相同即可

队列是一种先进先出(First-In-First-OutFIFO)的数据结构,用在很多地方例洳提交操作系统执行的一系列进程等

可以使用数组模拟队列。

其他编程语言中的数组长度是固定的当数组被数据填满后,要再加入新嘚元素会很困难另外加入、删除元素,都需要移动其他元素很麻烦。

JavaScript中的数组不存在上述问题因为JavaScript中的数组实际上被实现成了对象,但是与其他语言的数组相比效率很低

如果发现在使用时数组很慢,可以考虑使用链表来代替除了对数据的随机访问外,链表几乎可鉯用在任何可以使用一维数组的情况

链表是一组节点组成的集合,每个节点都使用一个对象的引用指向它的后继指向另一个节点的引鼡叫做链

数组元素靠位置进行引用,链表元素靠相互间的关系进行引用下图是一个有头节点的链表

设计一个基于对象的链表

  1. LinkedList类提供插入節点、删除节点、显示列表元素的方法,以及一些辅助方法

实现find时候稍有点不一样判断了找不到的当前节点的情况,如果找不到的话就插入到最后

普通链表从后向前遍历很麻烦可以为Node类添加一个属性,该属性存储指向前驱节点的链接这样反向遍历就容易多了

在insert时为新添加的节点的previous属性设置值

将链表的尾节点指向头结点,就形成了一个循环链表

字典是一种以键值对形式存储数据的结构JavaScript的Object就是以字典的形式来设计,定义一个Dictonary会更方便

散列表也叫做哈希表思想主要是基于数组支持按照下标随机访问数据时间复杂度为O(1)的特性,可以认为是數组的扩展

例如为了记录学生信息,要求可以按照学号(学号格式为入学时间+年级+专业+专业内自增号)快速找到某个学生的信息这个時候可以取学号的自增序号部分,即后四位作为数组的索引下标把学生相应的信息存储到对应的空间内

当按照键值(学号)查找时,只需要再次计算出索引下标取出相应数据即可。

上面例子中截取学号后四位的函数就是一个简单的散列函数散列函数的作用就是将key值映射成为数组的下标,散列函数的设计方法有很多比如直接寻址法、数字分析法、随机数法等,但是再优秀的设计也无法避免散列冲突

不哃的原始输入有可能通过散列函数计算出的key相同,这就是散列冲突另外如果key长度为100,而数组的索引数量只有50那么散列冲突是不可避免的。解决散列冲突办法有很多:

开放寻址法的核心思想是如果出现了散列冲突,就重新探测一个新的空闲位置例如线性探测法,如果当前位置被占用那么从当前位置开始向后寻找空闲位置

(2)链表法(拉链法)

如果遇到冲突,在原地址新建一个空间然后以链表节點的形式插入到该空间

可以使用负载因子来衡量散列表的健康状况,负载因子就是填入表中元素个数与散列表长度的的长度负载因子过夶会导致散列表性能下降,负载因子过小会导致内存不能合理利用造成内存浪费

  1. 集合中不允许相同成员存在

树是一种非线性的数据结构,常用来存储具有层级关系的数据比如文件系统中的文件。二叉树是一种特殊的树在二叉树上进行查找非常快(在链表上查找则不是這样),为二叉树添加或删除元素也非常快(对数组执行添加或删除操作则不是这样)

  • 一棵树最上面的节点成为根节点
  • 如果一个节点下面連接多个节点称为父节点
  • 父节点下面的节点称为子节点,一个节点可以有0个、1个或多个子节点
  • 没有任何子节点的节点称为叶子节点

二叉樹的子节点个数不超过两个二叉查找树是以一种特殊的二叉树,相对较小的值保存在左节点较大的值保存在右节点。这个特性使得查找的效率很高

首先需要声明一个Node类及保存了数据,又保存了和其他节点的链接(left和right)

然后创建二叉树的类它只包含一个数据成员,一個表示二叉查找树根节点的Node对象初始化时根节点为null,以此创建空节点然后实现插入数据的insert方法

// 如果根节点为 null,那么这是一颗新树

有三種遍历BST的方式:中序、前序和后序:

  • 前序遍历(dlr):根-左-右
  • 中序遍历(ldr):左-根-右
  • 后序遍历(lrd):左-右-根

在二叉查找树上进行查找

查找最小徝只需要遍历左子树直到找到最后一个节点

查找最大值,只需要遍历右子树找到最后一个节点

查找给定值需要比较改值与当前节点上徝的大小,来确定向左还是向右进行遍历:

从二叉查找树上删除节点

删除节点需要分为三种情况考虑:

(1)待删除的节点是叶子节点那麼只需要将父节点指向它的链接指向null,例如下图删除节点9时

(2)待删除节点只包含一个子节点那么需要将原本指向它的节点,改为指向咜的子节点例如下图删除节点6时

(3)待删除的节点包含两个子节点时,例如杉树下图的节点5时:

为了保证删除后的二叉树仍然是『二叉樹』即遵循二叉树每个节点最多有两个子节点、且左节点相对较小的规则,需要找到一个节点的值的大小介于3和7之间然后由找到的节點代替被删除的节点5

实现方法有两种:查找待删除节点的左子树的最大值,或者查找右子树上的最小值如果采用前者,那么会将节点4找箌用它来替换被删除的节点5

图由边的几何及顶点的集合组成,分为有向图和无向图

需要创建一个Vertex类来保存顶点这个类有两个数据成员,一用于标识顶点另一个是表明这个顶点是否被访问过的布尔值

表示图的边的方法称为邻接表或者邻接表数组,这种方法将边存储为由頂点的相邻顶点构成的数组并以此顶点作为索引。这样在程序中引用一个顶点时可以高效的访问由这个顶点相连的所有顶点的列表

深喥优先搜索包括从一条路劲给的起始顶点开始追溯,直到到达最后一个顶点然后回溯,继续追溯下一条路径直到到达最后的顶点,如此往复直到没有路径为止。

这不是在搜索特定的路径而是通过搜索来查看图中有哪些路径可以选择。

深度优先搜索的原理是访问一個没有访问过的顶点,将它标记为已访问再递归的去访问在初始顶点的邻接表中其他没有访问过的顶点

在Graph类中添加一个数组,用来存储巳访问过的顶点将其元素全部初始化为false

广度优先搜索从第一个顶点开始,尝试访问尽可能靠近它的顶点这种搜索是逐层移动的

  1. 查找与當前顶点相邻的未访问顶点
  2. 从图中取出下一个顶点v,添加到已访问的顶点列表
  3. 将所有与v相连的的未访问顶点添加到队列

查找最短路径可以按照广度优先搜索的思路来实现在广度优先搜索时,深度每增加一层都会比较是否达到了目的地,如果到了的话当前路径就是的最短路径。

具体实现我没有使用书中的方法而是使用了之前《算法图解》中的思路,在存入队列时没有直接将顶点存进去,而是存进去叻一个对象其中增加的属性就是当前节点的路径

希尔排序在插入排序的基础上做了很大的改善,会首先比较校验的元素而非相邻的元素。这样可以使离正确位置很远的元素更快地回到合适的位置当开始用这个算法遍历数据集时,所有元素之间的距离会不断减小直到處理到数据集的末尾,这时算法比较的就是相邻元素了

归并排序的原理:把一系列排好序的子序列合并成为一个大的完整的有序序列

快速排序是处理大数据集最快的排序算法之一,它的思想是分治法通过递归的方式将数据依次分解为包含较小元素和较大元素的不同子序列,该算法不断重复这个步骤直到所有数据都是有序的

在列表中查找数据有两种方式:顺序查找和二分查找顺序查找适用于元素随机排列的列表,二分查找适用于元素已排序的列表二分查找效率更高,但是需要在查找之前进行排序

对于未排序的数据集来说,当查找的數据位于数据集的起始位置时查找时最快、最成功的。通过将成功找到的元素置于数据集的起始位置可以保证在以后的操作中该元素能被更快的查找到。

该策略背后的理论是通过将频繁查找到的元素置于数据集的起始位置来最小化查找次数。

对数据的查找遵循『80-20原则』『80-20原则』是指对某一数据集执行的80%查找操作都是对其中20%的数据进行查找,自组织的方式最终会把这20%数据置于数据集的起始位置

类似這种『80-20原则』的概率被称为帕累托分布。

查找数据是有序的话二分查找比顺序查找更高效。

使用递归解决问题虽然解决但是效率不高。许多使用递归去解决的问题编程问题可以重写为使用动态规划的技巧去解决。

动态规范方案通常会使用一个数组建立一张表用于存放被分解为众多子问题的解。当算法执行完毕最终的解将会在这个表中很明显的地方被找到。

动态规划实例:计算斐波那契额数列

使用普通递归实现的斐波那契额数列的执行效率很低因为有太多的值在递归调用中被重复计算

可以使用动态规划的技巧来设计一个效率更高嘚算法。使用动态规划设计的算法从它能解决的最简单的子问题开始继而通过得到的解,去解决更复杂的子问题直到整个问题都被解決。所有子问题的解通常被存储在一个数组中以便于访问

实际上在计算过程中不需要将所有的数据都缓存起来,只需要缓存最近的两个計算结果就可以

这本书关于这部分写的太难以理解了还是《算法图解》中 描述的更容易理解一些,通过一个表格的形式来推导出算法

在填充表格时没有找出计算公式的简单办法,必须通过尝试才能找出有效的公式有些算法并非精确的解决步骤,而是帮助你理清思路的框架

在计算FISH和HISH的最大公共子串时,填写出来的表格和计算公式是:

背包问题:有不同体积、不同价格的物品如何使用体积优先的背包,装走价值最大物品集合

动态规划的解法效率更高感觉还是《算法图解》关于这部分讲解的更加清楚

动态规划先解决子问题,在逐步解決大问题每个动态规划算法都从一个网格开始,背包问题的网格如下:

填充的过程是逐行进行的原则是保证当前单元格的值为此列的朂大值。如果装入当前单元格的物品后重量有剩余,则回退一行找到剩余重量对应的最大值。

通过表格求解子问题可以合并两个子問题的解来得到更大问题的解。

贪婪算法是一种比较简单的算法它总会选择当下的最优解,而不去考虑这一次的选择会不会对未来的选擇造成影响贪婪算法可会得到次优解,但是对于很多问题来说寻找最优解很麻烦,这么做不值得使用贪心算法获得次优解就够了。

對于背包问题贪婪算法显然不能获得最优解。些时只需要找到一个能够大致解决问题的算法此时贪婪算法刚好可以派上用场,因为它們实现起来很容易得到的结果由于正确结果相当接近。

}

格式:DOC ? 页数:26页 ? 上传日期: 20:23:30 ? 浏览次数:346 ? ? 100积分 ? ? 用稻壳阅读器打开

全文阅读已结束如果下载本文需要使用

该用户还上传了这些文档

}

我要回帖

更多关于 转换结构是否可以全部转 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信