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];
           }
    }
};
posted @ 2021-04-22 23:09  Acx7  阅读(484)  评论(0编辑  收藏  举报