高級排序算法之希爾排序

前言

希爾排序是對插入排序的改進,引入維基百科的說明:php

希爾排序是基於插入排序的如下兩點性質而提出改進方法的:java

  1. 插入排序在對幾乎已經排好序的數據操做時,效率高,便可以達到線性排序的效率git

  2. 但插入排序通常來講是低效的,由於插入排序每次只能將數據移動一位github

原文連接希爾排序,本文將介紹希爾排序的實現思路,時間複雜度,穩定性等.數組

正文

希爾排序

主要思路

要改進插入排序,就要解決"插入排序每次只能將數據移動一位",而且利用"插入排序在幾乎已經排好序的數據操做時,效率高"的特性.邏輯描述以下.net

1. 初始時將數組劃分爲subArrsNum=arr.length/2個子數組
2. 對這些子數組subArrs使用插入排序排序
3. subArrsNum縮減爲一半,縮減後若是subArrsNum>=1,跳轉到2,不然 結束.

subArrs的定義以下code

subArrs[i]={arr[i],arr[i+k],arr[i+2k],...arr[i+nk]} i<k,arr.length/2 >= k >=1

這裏的難點在於對邏輯子數組的理解,下面結合subArrs的定義,舉例說明blog

arr={1,4,6,5,2,7,3,8}

初始時subArrsNum = arr.length/2=8/2=4,四個子數組分別爲排序

subArrs[0]={1,2}={arr[0],arr[0+4]}
subArrs[1]={4,7}={arr[1],arr[1+4]}
subArrs[2]={6,3}={arr[2],arr[2+4]}
subArrs[3]={5,8}={arr[3],arr[3+4]}

若是咱們想遍歷某個子數組,跨度應該等同於subArrsNum而非1.達成"每次能夠將數據移動不止一位"的效果",ip

而隨着子數組數量愈來愈少,數組也愈來愈有序,更好的利用"插入排序在幾乎已經排好序的數據操做時,效率高"這個特性,代碼以下

public void sort(Comparable[] arr) {
        if (arr.length <= 1) {
            return;
        }
        for (int subArrsNum = arr.length / 2; subArrsNum >= 1; subArrsNum /= 2) {
            //處理每一個子數組
            for (int secondElePos = subArrsNum; secondElePos < 2 * subArrsNum; secondElePos++) {
                for (int elePos = secondElePos; elePos < arr.length; elePos += subArrsNum) {
                    int toInsertELePos = elePos;
                    Comparable toInsertEleVal = arr[elePos];
                    for (int orderedElePos = elePos - subArrsNum; orderedElePos >= 0; orderedElePos -= subArrsNum) {
                        if (toInsertEleVal.compareTo(arr[orderedElePos]) < 0) {
                            arr[orderedElePos + subArrsNum] = arr[orderedElePos];
                            toInsertELePos = orderedElePos;
                        } else {
                            toInsertELePos = orderedElePos + subArrsNum;
                            break;
                        }
                    }
                    arr[toInsertELePos] = toInsertEleVal;
                }
            }

        }
    }

時間複雜度

最壞狀況下優於O(n^2),詳見 希爾排序&選擇排序&時間複雜度分析

是原地排序嗎

是的,希爾排序不須要使用額外空間

穩定嗎

不穩定,插入排序是穩定的,可是希爾排序不是,劃分子數組後,是對各個子數組分別進行插入排序,這時可能兩個相同的元素在不一樣的子數組的排序位置是不一樣的,例如[1,4,3,3,6,5],一次排序後爲[1,3,3,4,6,5],"3"的相對位置發生了變化


源碼地址github

相關文章
相關標籤/搜索