1.随机法
随机法依赖于随机数的统计特性。一个应用随机法的例子是快速排序。
随机选择一个值作为划分的依据,常被称为枢轴,将小于或等于枢轴的划在一堆,而大于枢轴的划在另一堆,重复这种划分,直到只有一个元素。
快速排序的平均性能不错,因为随机数的正态分布的结果是相对平衡的。
2.分治法
分治法包括三个步骤:
# 分解:将数据分解为更小、更容易管理的部分
# 求解:对每一个分解的部分进行处理
# 合并:对每部分处理的结果进行合并
分治法的实例就是归并排序。
归并排序方法描述:
# 分解阶段将数据分成两份
# 按照递归的方式对分解出的两部分应用归并排序
# 在合并阶段将两部分合并成一个排序好的集合
3.动态规划
动态规划和分治法相类似,都是将较大的问题分解为子问题,最后再将结果合并。然而,它们处理问题的方式与子问题之间的关系有关。
# 分治法:每一个子问题都是独立的,为此我们可以以递归的方式解决每一个子问题,然后将结果和其他子问题的结果合并。
# 动态规划:子问题间可能有关联
4.贪心法
在求解问题时候总能够做出在当前的最佳选择,它不是从整体最优上考虑,而是仅仅在某种意义上的局部最优解。
而遗憾的是,当前的最优解长远来看却未必是最优的。
贪心法的例子是霍夫曼编码,这是一个数据压缩算法。
霍夫曼编码最重要的部分是构建一棵霍夫曼树:
# 从它的叶子结点自底向上处理,将每个要压缩的符号和它们在数据中出现的频率一起作为二叉树的根节点保存
# 选择两棵拥有最小频率的根节点,作为左右子树结点,构造一棵新的二叉树,且保证新的二叉树根节点的频率值为左右子树频率之和
# 重复这样的步骤,得到唯一的一棵树
霍夫曼树的根节点包含数据中符号的总数,叶子节点包含原始的符号以及它们出现的频率
5.近似法
近似法不能计算出最优解,它只计算出足够好的解。
利用近似法解决哪些计算成本很高但是又因为其本身十分有价值而不愿放弃的问题,例子是推销员问题。
为推销员设计一条去好几个城市工作的路线,希望找到这样的路径,在回到出发点前恰好每一座城市都去过一次。
软件工程中的良好准则:
# 模块化
为了达到模块化目的的一种方法,将精力集中在黑盒上。
在软件开发中,黑盒代表一个模块,它的内部实现并不希望杯使用这个模块的用户看到。用户只能通过模块设计者预先定义好的公共接口和这个模块交互。
这样避免了模块内部的相耦合,这些是数据隐藏和封装的基本思想。
这种思想在面向对象语言中被强制施行,非面向对象语言也可以做到。
# 可读性
编写有意义的注释,使用贴切的标识符,编写自注释的代码
# 简洁性
# 一致性:建立编码约定并一直遵守这个约定