时空权衡

来源:互联网 发布:淘宝详情页教程 编辑:程序博客网 时间:2024/04/29 21:51

在解决问题的过程中,很难保证时间和空间的某一个达到最优,我们只能尽可能的优化时间和空间,达到时空权衡。

输入增强:对问题的部分或者全部输入做预处理,然后将获得的额外信息进行存储,以加速后面问题的解决。

代表算法:计数法排序  Boyer-Moore字符串匹配算法和Horspool提出的简化算法

预构造:简单地使用额外空间来实现更快和更方便的数据存储,它强调了时空权衡技术的两个方面:所讨论的问题在实际处理之前已经做过某些处理,这个技术

               只涉及存取结构。

代表算法:散列法  以B树作索引

动态规划:这个策略的基础是把给定问题中重复子问题的解记录在表中,然后求得所讨论的问题的解。

注: 时空权衡技术并不是相互独立的,有时候他们可以联合起来使得一个算法在运行时间上还是在消耗的空间上都达到最小化,具体来说使用一种空间效率很高的

         数据结构来表示问题的输入,这种结构又会反过来提高算法的时间效率(深度优先查找 广度优先查找)

计数排序:

比较计数排序:针对待排序列表中的每一个元素,算出列表中小于该元素的元素个数,并把结果记录在一张表中。这个“个数”记录了该元素在有序列表中的位置

       (数字是10表示在有序数组 的第11个位置)

理解;先初始化所有计数为0,每次遍历一个元素,并比较它后面元素的大小,它大则计数加1,后面的元素大则后面元素加1,直到最后一个元素,达到最终的状态。

应用:分布计数

            分布值指出了在最后的有序数组中,它的元素最后一次出现的正确位置,确定了分布值后,从待排的最后一个元素开始确定其位置。

            分布排序仅仅对输入数组A从头到尾连续处理两遍。它的效率类型比我们遇到的最高的排序算法-----合并排序、快速排序和堆排序------还要好

字符串匹配:

问题描述:字符串匹配问题要求在一个较长的称为文本的n个字符串中,寻找一个称为模式的给定的m个字符的串

                         最坏的情况:m(n-m+1)      O(nm)          平均效率:O(n+m)

解决思路:对模式进行预处理以得到他的一些信息,把这些信息存储在表里,然后在给定的文本中实际查找模式时使用这些信息。

代表算法:Knuth-Morris-Pratt算法  Boyer-Moore算法   Horspool算法

                    它们的主要区别在于如何对模式和文本中相应的字符进行比较:Knuth-Morris-Pratt算法是从左到右比较,而Boyer-Moore算法从右到左比较。

                     Boyer-Moore算法把模式和文本的开头字符对齐。如果第一次尝试失败了,它把模式向右移动,只是每次尝试过程中的比较才是从右到左,即从模式

                     的最后一个字符开始。而Horspool算法是Boyer-Moore算法的简化版

   注:每种算法的区别在于他们他们匹配模式的时候,从最右边的模式开始匹配,确定移动距离的不同。

           Horspool算法:                模式的长度m(如果c不包含在模式的前m-1个字符中)

                                         t(c)={

                                                         模式前m-1个字符中最右边的c到模式最后一个字符的距离(在其他情况下)


           Boyer-Moore算法:         d1        ,k=0                   其中,d1=max{t1(c)-k,1}

                                        d={

                                                       max{d1,d2}, k>0

            我们关心的是如何在不错过任何可能的匹配子串的前提下,把模式移动的越远越好,所以我们只取这两个距离中的最大值。我们知道Boyer-Noore算法的最差效率是线性的。虽然这个算法的速度非常快,而且当字母表的规模很大时更是这样。

散列法:

基本思想:它是把键分布在一个称为散列表的一维数组H[0..m-1]中,我们可以通过对每个键计算某些被称为散列函数的预定义函数h的值,来完成这种分布。该函数为每个键                        指定一个称为散列地址的位于0到m-1之间的整数。

这种映射到散列地址有可能会遇到碰撞,一些解决碰撞机制的有:开散列(分离链)  闭散列(开式寻址)

开散列:先计算键值,然后在散列表中查找相应的键,如果一个链表有碰撞,我们需要连续比较,最终确定查找是否失败。

                一般来说查找的效率取决于链表的长度,而这个长度又取决于字典和散列表的长度以及散列函数的质量。

负载因子:如果该散列函数大致均匀的将n个键分布在散列表的m个单元格中,每个链表的长度大约相当于n/m个键,其比率a=n/m称为散列表的负载因子

插入和删除操作,是一个常数时间的操作,与n和m无关。

闭散列(开式寻址):在闭散列中所有的键都存储在散列表本身,而没有使用链表本身(意味着表的长度m至少必须和键的数量n一样大)。

 闭散列解决碰撞机制:-----线性探索

  它检测碰撞发生处后面的单元格,如果该单元格为空,新的键就放在那里;如果下一个单元格也被占用了,就检查改单元格的直接后继是否可用,依次类推。

如果到达了散列表的尾部,查找就折回表的开始处。

延迟删除:用一个特殊的符号来标记曾经被占用过得位置,以把他们可那些未被占用过得位置区分开。所以查找和插入效率一样,删除需要特殊处理一下。

闭散列解决碰撞机制:-----双散列

为了解决聚类这样的碰撞情况,引入双散列法,我们使用了另一个散列函数S(K),用来确定在一个位于l=h(K)的碰撞发生后,所使用的探查序列的固定增量

    (l+s(K)) mod m, (l+2s(K)) mod m, ...       增量s(K)和标的长度必须是互质的,唯一的公因数是1。 双散列的性能比线性探查好,在使用优秀的散列函数的时候,

当散列接近满的时候,它的性能也会恶化,这个时候就需要重散列。

重散列:扫描当前的表,把它所有的键重新放置到一个更大的表中。


B树:它对2-3树允许查找树的同一个节点包含多个键的思想进行拓展。

           具体B树结构如下图所示:

           

一棵次数为m>=2的B树必须满足下面这些结构上的特性:

1)它的根要么是一个叶子,要么具有2到m个子女

2)除了根和叶子以外的每个节点,具有【m/2】到m个子女

3)这棵树是(完美的)平衡的,也就是说,它的所有叶子都在同一层次。

B树并不只是和大型文件的索引联系在一起,它可以被看作若干种查找树中的一种。通过B树结构,我们所实现的查找,插入和删除操作也只需要

执行很少几次的磁盘存取。






    

0 0
原创粉丝点击