2-路插入排序(Two-Way Insertion Sort)
算法介绍:
2-路插入排序是在折半插入排序的基础上改进的,插入排序的时间主要花在比较和移动这两种操作上。2-路插入排序可以减少排序过程中移动记录的次数,但为此需要借助n个记录的辅助空间。
算法描述:
利用一个与排序序列一样大小的数组作为辅助空间,设置first和final指针标记辅助数组开始位置和最后位置。遍历未排序序列,如果待插入元素比已排序序列最小的元素(first位置)小,则first位置前移,将待排序元素插入first位置;如果待插入元素比已排序序列最大的元素(final位置)大,则final位置后移,将待排序元素插入final位置;如果待插入元素比最小大,比最大小,则需要移动元素,过程类似直接插入排序,不过考虑到循环使用数组,对于下标的处理有些许不同。处理完最后一个元素后,将排序记录复制到原来的顺序表里。
性能分析:
时间复杂度:O(N^2)
空间复杂度:O(N)
稳定性:稳定
虽然减少了移动次数,但移动次数还是占大部分,移动次数大约为(n^2)/8次,并不能避免移动操作。并且当第一个元素是最大或最小关键字时,2-路插入排序就完全失去了它的优越性。
代码实现:
// C++代码 class TwoWayInsertionSort { public: static void twoWayInsertionSort(int array[], int length) { const int len = length;// 用于定义辅助数组 int temp[len];// 辅助数组 int first = 0;// 指示开始位置 int final = 0;// 指示最后位置 temp[0] = array[0];// 加入第一个元素 for (int i = 1; i < length; ++i) {// 遍历未排序序列 // 由于循环使用数组,以下过程都需要取余操作保证数组下标合法 if (array[i] < temp[first]) {// 待插入元素比最小的元素小 first = (first - 1 + length) % length;// 开始位置前移 temp[first] = array[i];// 插入元素 } else if (array[i] > temp[final]) {// 待插入元素比最大的元素大 final = (final + 1 + length) % length;// 最后位置后移 temp[final] = array[i];// 插入元素 } else {// 插入元素比最小大,比最大小 int j = (final + 1 + length) % length;// 用于移动元素 while (temp[(j - 1) % length] > array[i]) {// 元素后移 temp[(j + length) % length] = temp[(j - 1 + length) % length]; j = (j - 1 + length) % length; } temp[(j + length) % length] = array[i];// 插入元素 final = (final + 1 + length) % length;// 最后位置后移 } } // 将排序记录复制到原来的顺序表里 for (int k = 0; k < length; ++k) { array[k] = temp[(first + k) % length]; } } };