排序:基础的排序分为三类:插入(直接插入、shell)、选择(直接选择、堆排序)、交换(冒泡、快速)。极值:动态规划、贪心、回溯。
这里涉及的内容很多,不是一篇博客能说清楚的,这里宏观上,对它们做个对比和总结。
1.1 插入排序
直接插入排序:对待排序的记录逐个进行处理,每个新记录与同组那些已经排好序的记录进行比较,然后插入到适当的位置。如果按从小到大排序,对已经排好序的记录按照从大到小的顺序,依次与新纪录进行比较,直到找到一个不大 于新纪录的值,这就是新记录应该插入的位置;依次把新纪录插入到逐步扩大的已排序子序列中,直到最后完全排好序。
shell排序:Shell排序是对直接插入排序的优化。将带排序序列分为若干个子序列(即分组),要保证子序列中的记录在原始数组中不相邻,且间距相同,分别对这些子序列进行插入排序;然后减少记录间的间距,减少小序列的个数,将原始序列分为更大、更有序的子序列,分别进行插入排序;重复进行下去,直到最后间距减少为1,然后对整个序列进行插入排序。
1.2 选择排序
直接选择排序:逐个找出第i小的记录,并将整个记录与数组的第i个位置的记录交换,第i小的记录一次交换到位。
堆排序:堆排对直接选择排序的优化。对所有记录建立最大堆,取出堆顶的最大记录与数组末端的记录交换,原数组末端元素临时处于根节点;将剩下的n-1个记录重新调整为堆,再取新堆顶最大记录,与第n-2的位置交换.......;不断重复这一操作,直到堆为空,得到从小到大排序的数组。
1.3 交换排序
冒泡排序:从数y末端开始,不断比较相邻记录,不满足排序要求就交换;第一轮冒泡过程,r0是最小的记录,因此第二轮冒泡只需要对rn-1到r1进行比较。第二次冒泡完,次小的记录,就被推到r1上。依次类推,直到数组中所有记录都排好序为止。
快速排序: 快速排序是对冒泡排序的优化。从待排序列中,任意选择一个记录k作为轴值,将剩余的记录分割成左子序列L和右子序列R。L中所有记录都小于或等于k,R中记录都大于等于k,因此k正好位于正确的位置。对于序列L和R进行快速排序,直到子序列中只含有0或1个元素,退出递归。
2.1 动态规划
动态规划与分治法类似,将带求解的问题分解成若干个子问题,先求解子问题,然后从子问题的解得到原问题的解。动态规划法求解的问题,分解得到的子问题往往不是独立的。动态规划法通常用于求解具有某种最优性质的问题。动态规划法求解可以分一下几个步骤:
1) 找出最优解的性质,刻画结构特征
2) 递归的定义最优解的值
3) 以自底向上的方式计算出最优值
4) 根据计算最优值时得到的信息,构造一个最优解。
2.2 贪心
贪心法在解决问题的策略上是根据当前以后的信息作出选择,而且一旦作出了选择,不管将来有什么结果,这个选择都不会改变。所以,贪心法并不是从整体最优考虑,它的选择某种意义上的局部最优。这种最优选择并不能保证总能获得全局最优解,但通常得到较好的近似最优解。
2.3 回溯
回溯法有“通用的解题法”之称,用它可以系统的搜索一个问题的所有解,或任意一解。t它在包含问题的所有解的解空间树中,按照深度优先的策略,从根节点出发搜索解空间树。算法搜索到解空间树的任一节点时,总是先判断该节点是否肯定不包含问题的解。如果肯定不包含,则跳过对以该节点为根的子树的系统搜索,逐层向其祖先节点回溯;否则,进入该子树,继续按深度优先的策略搜索。回溯法在用来求问题的所有解时,要回溯到根,且节点的所有子树都已被搜索遍才结束。而用来求问题的任一解时,只要搜索到问题的一个解就可以结束。
对比以上各算法的关系,简单画了如下思维导图: