插入排序

基本思想

在整个数组中找出最小的元素然后和第一个元素进行交换;然后从剩下的元素中找出最小的元素和第二个元素进行交换;以此类推,直到将无需部分全部变成有序为止。

代码

template<typename T>
void insertionSort(T q[], int n) {
    for (int i=1; i<n; i++) {
        for (int j=i; j>=1; j--)
            if(q[j-1] > q[j])
                swap(q[j], q[j-1]);
            else
                break;
    }
}
  • 优化1, 提前终止内层循环
template<typename T>
void insertionSort(T q[], int n) {
    for (int i=1; i<n; i++) {
        // 寻找元素arr[i]合适的位置, 和选择排序相比,最大的区别就是该算法可以提前终止内层循环
        for (int j=i; j>=1 && q[j-1] > q[j]; j--)
                swap(q[j], q[j-1]);
    }
}
  • 优化2: 将交换操作修改为比较后赋值操作
template<typename T>
void insertionSort(T q[], int n) {
    // 寻找元素q[i]合适的插入位置
    for (int i=1; i<n; i++) {
        // 将待考察的元素赋值一份副本, 然后将它和它前面的元素比较
        T e = q[i];
        // j保存元素e应该插入的位置
        int j;
        for (j=i; j>=1 && q[j-1] > e; j--)
            // 如果比它前面的元素小, 则更新
            // 将交换操作修改为赋值操作
            q[j] = q[j-1];
        // 将考察的元素放在正确的位置
        q[j] = e;
    }
}
  • 对q[l...r]范围的数组进行插入排序
void insert_sort(int q[], int l, int r) {
    for (int i=l+1; i<=r; i++) {
        int e = q[i]; // 待考查元素的副本, 用该副本和它前面的元素依次比较
        int j; // 待考察元素最终插入的位置
        for (j=i; j>=l && q[j-1] < e; j--){
            // 如果待考察元素比它前面的元素小, 则说明当前的索引j不是最终插入的位置,需要更新j
            q[j] = q[j-1];
        }
        q[j] = e;
    }
}

希尔排序

直接插入排序算法的一种更高效的改进版本。希尔排序是非稳定排序算法。该方法因D.L.Shell于1959年提出而得名。

基本思想

希尔排序是把记录按下标的一定增量分组,对每组使用直接插入排序算法排序;随着增量逐渐减少,每组包含的关键词越来越多,当增量减至1时,整个数组恰被分成一组,算法便终止。

代码

template<typename T>
void shellSort(T q[], int n) {
    int h = 1;
    while(h < n/3)
        h = h*3 + 1;
    while(h >= 1) {
        // h-sort the array
        for (int i=h; i<n; i++) {
            T e = q[i];
            int j;
            // 对q[i], q[i-h], q[i-2*h]....进行插入排序
            for (j=i; j>=h && q[j-h] > e; j -= h) 
                q[j] = q[j-h];
            q[j] = e;
        }
        h /= 3;
    }
}
  • 对q[l...r]范围的数组进行希尔排序
// 修改插入排序, 传入增量h
template<typename T>
void insertionSort(T q[], int l, int r, int h) {
    for (int i=l+h; i<=r; i++) {
        T e = q[i];
        // j保存元素e应该插入的位置
        int j;
        // 对 q[i], q[i-h], q[i-2*h], q[i-3*h]... 使用插入排序
        for (j=i; j>=l+h && q[j-h] > e; j-=h)
            q[j] = q[j-h];
        q[j] = e;
    }
    return;
}
template<typename T>
void shellSort(T q[], int l, int r) {
    /* Knuth序列: 唐纳德, 以为图灵奖获得者发明的序列
    h=1
    h=3*h+1 */
    // 计算 increment sequence: 1, 4, 13, 40, 121, 364, 1093...
    int h = 1;
    while( h < (r-l+1)/3 )
        h = 3 * h + 1;
    while(h>=1) {
        // h-sort the array
        insertionSort(q, l, r, h);
        h /= 3;
    } 
}
  • 优化: 使用Knuth序列

    /* 
    Knuth序列: 唐纳德, 以为图灵奖获得者发明的序列
    h=1; h=3*h+1 
    */
    // 计算 increment sequence: 1, 4, 13, 40, 121, 364, 1093...
    int h = 1;
    while( h < (r-l+1)/3 )
        h = 3 * h + 1;

alits
7 声望0 粉丝

« 上一篇
linux 基础