C语言 希尔排序

希尔排序简介

希尔排序(Shell’s Sort)是插入排序的一种又称“缩小增量排序”(Diminishing Increment Sort),是直接插入排序算法的一种更高效的改进版本,时间复杂度为O(n^2)。

希尔排序的模拟过程可以看链接:ShellSortion

在看具体代码实现之前,需要先看我之前的文章中关于插入排序的代码实现:插入排序

实现过程

为了比较容易地理解插入排序,我们可以列出一组数据,比如:
1,5,4,3,7

我列出了两种方法分别说明插入排序的实现过程,你可以选择自己喜欢的方法:

第一种

对于希尔排序算法来说:
1. 计算步长(间隔):4/2=2, 分出了两个过程:
(1). 根据步长,取出数据:1, 4, 7,进行插入排序:
1, 4, 7
(2) 根据步长,取出数据:‘5, 3’,进行插入排序:
5,3
完成上面两个过程后,现在的数据为1,3,4,5,7
2. 计算步长:4/4=1, 根据步长, 取出数据:1,3,4,5,7,进行插入排序:
1,3,4,5,7

第二种

这里写图片描述

分析以上过程,我们发现希尔排序有两个要素:
1. 进入插入排序前,我们需要得到步长,还有起始地址。
2. 步长需要通过数据长度/2得到。

代码实现

首先我们需要对插入排序进行一些修改:

void pushFront(int *a, const int length, const int key, const int dk) {
    //将所有a[j]到a[length]都往后推一格
    int tmp = a[length];
    for (int i = length; i >key; i  = i - dk) {
        a[i] = a[i- dk];
    }

    a[key] = tmp;
};

void insertSort(int *a, const int length, const int dk, const int div) {
    //dk 步长, div 初始地址
    for (int i = div; i < length; i = i + dk) {
        for (int j = div; j < i; j = j + dk) {
            if (a[i] < a[j]) {
                pushFront(a, i, j, dk);
                break;
            }

        }
        print(a, length);
    }
}

相比之前的插入排序,我们加入了步长和起始地址,所以我们只需要计算完成步长和初始地址的迭代计算即可:

void shellSort(int *a, const int length) {
    for (int i = 2; length / i > 0; i = i * 2) {
        int dk = length / i;
        for (int div = 0; div < length / i + 1; div++) {
            insertSort(a , length, dk, div);
        }
    }
}

完整的代码:

#include <stdio.h>

void print(const int *a, const int length) {
    int i;
    for (i = 0; i<length; i++) {
        printf("%d ", a[i]);
    }
    putchar('\n');
}

void pushFront(int *a, const int length, const int key, const int dk) {
    //将所有a[j]到a[length]都往后推一格
    int tmp = a[length];
    for (int i = length; i >key; i  = i - dk) {
        a[i] = a[i- dk];
    }

    a[key] = tmp;
};

void insertSort(int *a, const int length, const int dk, const int div) {
    //dk 步长, div 初始地址
    for (int i = div; i < length; i = i + dk) {
        for (int j = div; j < i; j = j + dk) {
            if (a[i] < a[j]) {
                pushFront(a, i, j, dk);
                break;
            }

        }
        print(a, length);
    }
}

void shellSort(int *a, const int length) {
    for (int i = 2; length / i > 0; i = i * 2) {
        int dk = length / i;
        for (int div = 0; div < length / i + 1; div++) {
            insertSort(a , length, dk, div);
        }
    }
}

void main() {
    const int length = 5;
    int my_array[5] = { 1,5,7,3,4};
    print(my_array, length);

    shellSort(my_array, length);
    print(my_array, length);
}

代码精简

void SelectSort(int r[],int length){  
    int i ,j , min ,max, tmp;  
    for (i=0 ;i < length/2;i++){    
        min = i; 
        max = i;
        //find minimum
        for (j= i+1; j< length-i; j++){  
            if (r[j] > r[max]){
                max = j ; 
                continue;  
            }    
                    if (r[j]< r[min]){   
                min = j ;   
                }
            }    
        tmp = r[i]; r[i] = r[min]; r[min] = tmp;  
        tmp = r[length-i-1]; r[length-i-1] = r[max]; r[max] = tmp;   
        }  
} 

猜你喜欢

转载自blog.csdn.net/fpk2014/article/details/80443605