算法I-IV中的一些小技巧
1.容器中循环时判断的操作有时可以通过对容器进行特殊的处理而避免。
①例如插入排序中判断是否插入在第一个元素,可以通过将最小元素放在容器初始位置而避免。
②归并排序中判断是否到容器尾部,可以通过在尾部加入一个比任何元素都大的元素而避免(标志关键字),也可以将容器变成bitonic(元素大小先增大后减小),然后分别从前往后,从后往前同时进行,这样到达某一段容器的结尾时,剩余一段容器的元素总比这个结尾小(因为是倒叙排列),如下所示:
原始两段数据: 1 3 5 2 4 6 8 9 bitonic后 1 3 5 9 8 7 6 4 2
左边的指针指向第一段数据的结尾5后,会指向第二段数据的结尾9,而此时第二段数据还有6,7,8,9没有排序,而9是右边数据最大的值,所以第一段的指针不会继续前进,第二段数据依次排序。避免了判断到结尾的操作。
③堆排序中,第一步建堆完成后构建顺序序列的过程中,取出堆顶的最大元素(或最小元素)后,交换末尾叶节点到堆顶后需要进行向下修复堆,通常此节点会从顶遍历到堆底(因为本身就是较小的或者较大的),而其中会进行很多次检测来判断是否到指定位置。此时只需要将刚刚移走的堆顶的两个子元素中最大(最小)的元素直接放到堆底,然后往往堆顶直接回溯,知道放到堆顶。
书上第九章9.4节中此处没有给具体方案,只是说了思路,因为顶节点交换后,子节点中最大的那个必定是下一个最大的元素。而自顶向下的比较次数要比自底向上的多(3>2),所以采用这样的思路。书上上这种方法需要薄记,所以旨在比较操作需要耗费较多时间的情况下使用。另外我自己找了一篇论文大家可以参考下:https://tech.hqew.com/fangan_1721896
更新:后来读STL源码剖析时,在4.7.2节的pop_heap算法中找到了上述改进修复堆的算法_adjust_heap。中文版p177页。
堆排序中还可以通过增加堆的叉数来减少堆的层数来减少比较次数。

浙公网安备 33010602011771号