【数据结构与算法分析】第十章 算法技巧设计

【数据结构与算法分析】第十章 算法技巧设计

1.贪婪算法

三种贪婪算法:

Dijkstra算法、Prim算法、Kruskal算法

贪婪算法的工作原理:

分阶段工作,在每一个阶段,选择最优的,不考虑将来的后果。

虽然贪心算法不能对所有问题都得到整体最优解,但对许多问题它能产生整体最优解。如单源最短路经问题,最小生成树问题等。在一些情况下,即使贪心算法不能得到整体最优解,其最终结果却是最优解的很好近似。

1.1 霍夫曼编码

贪婪算法的第二个应用,称为文件压缩。用于降低文件的总的所需的比特数。

例:一个文件中有10个a,15个e、12个i,3个s、4个t、13个空格和1个newline,总比特数为174

一般降低文件大小的策略:让代码的长度从字符到字符是变化不等的,使频率高的字符其代码短。

哈夫曼算法

基本定义:

  • 一棵树的权等于它的树叶的频率之和。

  • 每个字符代码的长度是否不同不重要,只要没有字符代码是别的字符代码的前缀即可,这种编码为前缀码。

  • trie树:每个字符通过从根节点开始用0指示左分支,用1指示右分支。

哈夫曼算法过程:假设字符个数为C,每个都选取最小权的两棵树进行合并,形成新树,进行C-1次后,得到最优哈夫曼编码树。称为贪婪算法原因是每个阶段都选择最小的两棵树,未进行全局的考虑

具体过程如下:(1)取最小权为s和nl进行第一个合并,产生新树T1

(2)取最小权T1和t进行第二次合并,取最小权T2和a进行第三次合并

(3)取最小权i和sp进行第四次合并

(4) 取最小权T3和e进行第五次合并

(5)取最小权T4和T5进行第六次合并

1.2近似装箱问题

装箱问题分为联机装箱和脱机装箱两种。例:对一批大小为0.2、0.5、0.4、0.7、0.1、0.3、0.8的货物进行装箱,箱子大小为1

联机算法

下项合适算法

当处理任何一项物品时。检查它是否能装进刚刚装进物品的同一个箱中,不行就开辟一个新箱

首次适合算法

依次扫描前面的箱子把新的物品放在能盛下它的第一个箱子中。

最佳适合算法

该算法是把一项新物品放到所有箱子中能容纳它的最满的箱子中。

脱机算法

将各项物品排序,把最大的物品放在最先,应用首次适合算法或最佳适合算法,得到首次适合递减算法和最佳适合递减算法。

2.分治算法

分治算法要求最优子结构 和独立(非重叠)子问题,算法通常由两部分组成divide-conquer。思路是递归解决较小的子问题,然后从子问题的解构建原问题的解。分治算法通常至少含有两个内部递归

伪代码:算法描述语言

最近点问题:

naive算法花费O(N*N)时间复杂度,可以将点空间划分为两半,递归的解两个子问题,然后进行合并

选择问题:

五分化中项的中项方法系统开销太大,根本不实用。

整数相乘:

不仅要进行子问题的划分,还要通过合并变换减少实际的乘法次数

矩阵相乘:

两个矩阵的乘法:

矩阵乘法代码实现:

void MatriMulitiply(Matrix A,Matrix B,Matrix C,int N)
{
    int i,j,k;
    for(i=0;i<N;i++)
        for(j=0;j<N;j++)
            C[i][j]=0;
    for(i=0;i<N;i++)
        for(j=0;j<N;j++)
            for(k=0;k<N;k++)
                C[i][j]+=A[i][k]*B[k][j];
}

3.动态规划

通常递归算法会重复一些子问题,造成不必要的性能下降。动态规划的思路是弃用递归,将子问题的答案系统的记录在中间表(table)中。其特点是最优子结构和重叠子问题。

4.随机化算法

好的随机化算法没有不好的输入,而只有不好的随机数(考虑快排枢纽元的选取)。

4.1随机数发生器

实现真正的随机数生成器是不可能的,依赖于算法,都是些伪随机数。

产生随机数最简答的方法是线性同余生成器

序列的最大生成周期为M-1,还需要仔细选择A,贸然修改通常意味着失败。需要注意的是,直接按照前面公式实现有可能发生溢出大数的现象,通常需要进行变换。

4.2跳跃表

借助随机化算法实现以O(NlogN)期望时间支持查找和插入操作数据结构。本质是多指针链表。当查找时,从跳跃表节点的最高阶链开始寻找;当插入元素时,其阶数是随机的(抛硬币直到正面朝上时的总次数)

4.3素性测试

某些密码方案依赖于大数分解的难度。费马小定理(下1):如果定理宣称一个数不是素数,那这个数肯定不是素数;若宣称是素数的话,有可能不是素数。可借助平方探测的特殊情况(下2)加以判断。

5.回溯算法

虽然分析回溯算法的复杂度可能很高,但实际上的性能却很好,明显优于穷举法。有时还会借助裁剪的方法进一步降低复杂度。与分支限界法不同,回溯算法通常是深度优先递归的搜索所有解,而分支限界通常是广度优先,找出满足条件的一个解。

猜你喜欢

转载自blog.csdn.net/zhangxiafll/article/details/82151474
今日推荐