希尔排序 shell sort

希尔排序

  • 时间复杂度:平均O(n^1.3),最好为O(n),最坏为0(n ^ 2)
  • 空间复杂度:O(1)
  • 稳定性:不稳定

算法解析:

  • 希尔排序是直接插入排序的一种改进,又称做缩小增量排序
  • 希尔排序是把待排序集合计算出一个增量集合Tn
  • 把待排序集合分成若干个子集,然后每个子集进行直接插入排序,知道Ti=1为止,排序结束
  • 遍历次数为增量集合的count数

举例

有一个集合如下图所示:

《希尔排序 shell sort》 list.png

计算增量:gap = length/3 + 1,自己可以查阅为什么是 除以3(除以3交换的次数最少,时间用的最少)

  • 第一次:gap = 4,把待排序列划分为4个子序列

    《希尔排序 shell sort》 第一次.png

  • 第二次 :gap = 2,把待排序列划分为2个子序列

    《希尔排序 shell sort》 第二次.png

  • 第三次:gap = 1,进行一次直接插入排序,排序结束

排序结果:

《希尔排序 shell sort》 result.png

动画演示

《希尔排序 shell sort》 shellSort.gif

C语言实现

void shellSort(int arr[],int length) {
    //增量计算,计算间隔
    int gap = length/3 + 1;
    while (gap > 0) {
        for (int i = gap; i<length; i++) {
            int tmp = arr[i];
            int j = i-gap;
            if (j >= 0 && arr[j] > tmp) {
                arr[j+gap] = arr[j];
                j-=gap;
            }
            arr[j+gap] = tmp;
        }
        if (gap == 1) { break; }
        gap = gap/3 + 1;
    }
}

OC实现

- (NSArray *)shellSort:(NSMutableArray *)arr {
    NSUInteger length = arr.count;
    NSInteger gap = length/3 + 1;
    while (gap > 0) {
        for (NSUInteger i = gap; i < length; i++) {
            NSNumber *tmp = arr[i];
            NSUInteger j = i-gap;
            if (j >= 0 && [arr[j] intValue] > [tmp intValue]) {
                arr[j+gap] = arr[j];
                j -= gap;
            }
            arr[j+gap] = tmp;
        }
        if (gap == 1) {break;}
        gap = gap/3 + 1;
    }
    return arr.copy;
}

Swift实现

func shellSort(arr: inout [Int]) -> Void {
    let length = arr.count
    var gap = length/3 + 1
    while gap > 0 {
        for index in 0..<length {
            let tmp = arr[index]
            var j = index-gap
            while j >= 0 && arr[j] > tmp {
                arr[j+gap] = arr[j]
                j = j - gap
            }
            arr[j+gap] = tmp
        }
        if gap == 1 { break }
        gap = gap/3 + 1
    }
}

以下实现来源于网络,未验证

c++实现

void shell_sort(const int start, const int end) {
    int increment = end - start + 1;    //初始化划分增量
    int temp{ 0 };
    do {    //每次减小增量,直到increment = 1
        increment = increment / 3 + 1;
        for (int i = start + increment; i <= end; ++i) {    //对每个划分进行直接插入排序
            if (numbers[i - increment] > numbers[i]) {
                temp = numbers[i];
                int j = i - increment;
                do {    //移动元素并寻找位置
                    numbers[j + increment] = numbers[j];
                    j -= increment;
                } while (j >= start && numbers[j] > temp);
                numbers[j + increment] = temp;  //插入元素
            }
        }
    } while (increment > 1);
}

js实现

function shellSort(arr) {
    var len = arr.length,
        temp,
        gap = 1;
    while(gap < len/3) {          //动态定义间隔序列
        gap =gap*3+1;
    }
    for (gap; gap > 0; gap = Math.floor(gap/3)) {
        for (var i = gap; i < len; i++) {
            temp = arr[i];
            for (var j = i-gap; j >= 0 && arr[j] > temp; j-=gap) {
                arr[j+gap] = arr[j];
            }
            arr[j+gap] = temp;
        }
    }
    return arr;
}

Python 代码实现

def shellSort(arr):
    import math
    gap=1
    while(gap < len(arr)/3):
        gap = gap*3+1
    while gap > 0:
        for i in range(gap,len(arr)):
            temp = arr[i]
            j = i-gap
            while j >=0 and arr[j] > temp:
                arr[j+gap]=arr[j]
                j-=gap
            arr[j+gap] = temp
        gap = math.floor(gap/3)
    return arr
}

Go 代码实现

func shellSort(arr []int) []int {
    length := len(arr)
    gap := 1
    for gap < gap/3 {
        gap = gap*3 + 1
    }
    for gap > 0 {
        for i := gap; i < length; i++ {
            temp := arr[i]
            j := i - gap
            for j >= 0 && arr[j] > temp {
                arr[j+gap] = arr[j]
                j -= gap
            }
            arr[j+gap] = temp
        }
        gap = gap / 3
    }
    return arr
}

Java 代码实现

public class ShellSort implements IArraySort {
    @Override
    public int[] sort(int[] sourceArray) throws Exception {
        // 对 arr 进行拷贝,不改变参数内容
        int[] arr = Arrays.copyOf(sourceArray, sourceArray.length);

        int gap = 1;
        while (gap < arr.length) {
            gap = gap * 3 + 1;
        }
        while (gap > 0) {
            for (int i = gap; i < arr.length; i++) {
                int tmp = arr[i];
                int j = i - gap;
                while (j >= 0 && arr[j] > tmp) {
                    arr[j + gap] = arr[j];
                    j -= gap;
                }
                arr[j + gap] = tmp;
            }
            gap = (int) Math.floor(gap / 3);
        }
        return arr;
    }
}

PHP 代码实现

function shellSort($arr)
{
    $len = count($arr);
    $temp = 0;
    $gap = 1;
    while($gap < $len / 3) {
        $gap = $gap * 3 + 1;
    }
    for ($gap; $gap > 0; $gap = floor($gap / 3)) {
        for ($i = $gap; $i < $len; $i++) {
            $temp = $arr[$i];
            for ($j = $i - $gap; $j >= 0 && $arr[$j] > $temp; $j -= $gap) {
                $arr[$j+$gap] = $arr[$j];
            }
            $arr[$j+$gap] = $temp;
        }
    }
    return $arr;
}
    原文作者:数据结构
    原文地址: https://www.jianshu.com/p/a49e9c1998d1
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞