基本介紹
歷史
- 插入排序在對幾乎已經排好序的數據操作時,效率高,即可以達到線性排序的效率。
- 但插入排序一般來說是低效的,因為插入排序每次只能將數據移動一位。
基本思想
穩定性
排序過程
縮小增量
Shell排序
算法分析
優劣
時間性能
希爾分析
代碼實現
偽代碼
inc ← round(n/2)
while inc > 0 do:
for i = inc .. n − 1 do:
temp ← a[i]
j ← i
while j ≥ inc and a[j − inc] > temp do:
a[j] ← a[j − inc]
j ← j − inc
a[j] ← temp
inc ← round(inc / 2.2)
Golang
func ShellSort(nums []int) []int{ //外層步長控制 for step := len(nums) / 2; step > 0; step /= 2 { //開始插入排序 for i := step; i < len(nums); i++ { //滿足條件則插入 for j := i - step; j >= 0 && nums[j+step] < nums[j]; j -= step { nums[j], nums[j+step] = nums[j+step], nums[j] } } } return nums}
vb.net
Function Shell(Byval lines() As Integer) As Integer() dim c() As Integer=lines.clone,div,i,j,k As Integer,Data As Integer if UBound(c)=1 then return lines For div=len/2 To 1 div/=2 For i=0 To div Step 1 For j=i To len-div For k=j to len Step div If(data[j]>data[k]) swapInt(data+j,data+k) End If Next Next Next NextEnd Function
javascript
var arr = [49, 38, 65, 97, 76, 13, 27, 49, 55, 04];var len = arr.length;for (var fraction = Math.floor(len / 2); fraction > 0; fraction = Math.floor(fraction / 2)) { for (var i = fraction; i < len; i++) { for (var j = i - fraction; j >= 0 && arr[j] > arr[fraction + j]; j -= fraction) { var temp = arr[j]; arr[j] = arr[fraction + j]; arr[fraction + j] = temp; } }}console.log(arr);
pascal
const size=12;type arr=array[1..size]ofinteger;var a:arr; i,j,k,t:integer;procedure DataInput;//生成隨機數列begin randomize; for i:=1 to size do begin a[i]:=random(99)+1; write(a[i]:3); end; writeln; end;procedure DataOutput;//輸出begin for i:=1 to size do write(a[i]:3); end;procedure insertionsort(var a:arr);begin for i:=2 to size do begin t:=a[i]; j:=i-1; while (j>0) and (t<a[j]) do begin a[j+1]:=a[j]; j:=j-1; end; a[j+1]:=t; end;end;begin DataInput; k:=size; while k>1 do begin k:=k div 2; for j:=k+1 to size do begin t:=a[j]; i:=j-k; while (i>0) and (a[i]>t) do begin a[i+k]:=a[i]; i:=i-k; end; a[i+k]:=t; end; end; DataOutput;end.
Kotlin
fun sort(arr: IntArray) { var gap = arr.size / 2 while (1 <= gap) { for (i in gap..arr.size - 1) { var j = i - gap val tmp = arr[i] while (j >= 0 && tmp < arr[j]) { arr[j + gap] = arr[j] j -= gap } arr[j + gap] = tmp } gap /= 2 }}
JAVA
public static void main(String [] args){ int[]a={49,38,65,97,76,13,27,49,78,34,12,64,1}; System.out.println("排序之前:"); for(int i=0;i<a.length;i++) { System.out.print(a[i]+" "); } //希爾排序 int d=a.length; while(true) { d=d/2; for(int x=0;x<d;x++) { for(int i=x+d;i<a.length;i=i+d) { int temp=a[i]; int j; for(j=i-d;j>=0&&a[j]>temp;j=j-d) { a[j+d]=a[j]; } a[j+d]=temp; } } if(d==1) { break; } } System.out.println(); System.out.println("排序之後:"); for(int i=0;i<a.length;i++) { System.out.print(a[i]+" "); } }
C#
using System;namespace ConsoleApplication8{ //希爾排序類 class ShellSorter { public void Sort(int[] list) { int _d = list.Length; int _len = list.Length; for (_d = _d / 2; _d > 0; ) { if (_d % 2 == 0) _d++; //按d分組 for (int i = 0; i < _d; i++) { //每組執行直接插入排序算法 for (int j = i + _d; j < _len; j += _d) { if (j < _len) { if (list[j] < list[j - _d])//後面小於前面 { int temp = list[j]; int k = 0; for (k = j - _d; k >= i && temp < list[k]; k -= _d)//比它大的元素後移動 { list[k + _d] = list[k]; } list[k + _d] = temp;//插入最後比它小的後面 } } } } Console.WriteLine("第一次d->" + _d); for (int i = 0; i < _len; i++) { Console.Write(string.Format("{0},", list[i])); } Console.WriteLine(""); _d = _d / 2; } } } public class MainClass { public static void Main(String[] args) { //模擬數據 int[] iArrary = new int[] { 1, 5, 3, 6, 10, 55, 9, 2, 87, 12, 34, 75, 33, 47 }; ShellSorter sh = new ShellSorter(); sh.Sort(iArrary); for (int m = 0; m <= 13; m++) { Console.WriteLine("{0}", iArrary[m]); } Console.ReadKey(); } }}
C語言
#include<stdio.h>#include<math.h>#define MAXNUM 10void main(){ void shellSort(int array[],int n,int t);//t為排序趟數 int array[MAXNUM],i; for(i=0;i<MAXNUM;i++) scanf("%d",&array[i]); shellSort(array,MAXNUM,(int)(log(MAXNUM+1)/log(2)));//排序趟數應為log2(n+1)的整數部分 for(i=0;i<MAXNUM;i++) printf("%d ",array[i]); printf("\n");}//根據當前增量進行插入排序void shellInsert(int array[],int n,int dk){ int i,j,temp; for(i=dk;i<n;i++)//分別向每組的有序區域插入 { temp=array[i]; for(j=i-dk;(j>=i%dk)&&array[j]>temp;j-=dk)//比較與記錄後移同時進行 array[j+dk]=array[j]; if(j!=i-dk) array[j+dk]=temp;//插入 }}//計算Hibbard增量int dkHibbard(int t,int k){ return (int)(pow(2,t-k+1)-1);}//希爾排序void shellSort(int array[],int n,int t){ void shellInsert(int array[],int n,int dk); int i; for(i=1;i<=t;i++) shellInsert(array,n,dkHibbard(t,i));}//此寫法便於理解,實際套用時應將上述三個函式寫成一個函式。
C++
template <typename _RIter>void insert_sort(_RIter st, _RIter ed, int delta) { for(_RIter i = st + delta; i < ed; i += delta) { for(_RIter j = i; j > st; j -= delta) if(*j < *(j - delta)) std::swap(*j, *(j - delta)); else break; }}template <typename _RIter>void shell_sort(_RIter st, _RIter ed) { for(int delta = ed - st; delta; delta /= 2) for(int i = 0; i < delta; i++) insert_sort(st + i, ed, delta);}
AS3
//需要排序的數組vararr:Array=[7,5,8,4,0,9];varsmall:int;//最小下標vartemp:int;for(vari:int=0;i<arr.length;i++){small=i;for(varj:int=i+1;j<arr.length+1;j++){if(arr[j]<arr[small]){small=j;}}if(small!=i){temp=arr[i];arr[i]=arr[small];arr[small]=temp;}trace(arr[i]);}
Ruby
def shell_sort(array) gap = array.size while gap > 1 gap = gap / 2 (gap..array.size-1).each do |i| j = i while j > 0 array[j], array[j-gap] = array[j-gap], array[j] if array[j] <= array[j-gap] j -= gap end end end arrayend
PHP
function shell_sort(&$arr) { if(!is_array($arr)) return; $n = count($arr); for ($gap = floor($n/2); $gap > 0; $gap = floor($gap/=2)) { for($i = $gap; $i < $n; ++$i) { for($j = $i - $gap; $j >= 0 && $arr[$j + $gap] < $arr[$j]; $j -= $gap) { $temp = $arr[$j]; $arr[$j] = $arr[$j + $gap]; $arr[$j + $gap] = $temp; } } }}
Python
def shell(arr): n=len(arr) h=1 while h<n/3: h=3*h+1 while h>=1: for i in range(h,n): j=i while j>=h and arr[j]<arr[j-h]: arr[j], arr[j-h] = arr[j-h], arr[j] j-=h h=h//3 print arr