Shell 排序法 - 改良的插入排序

Shell排序法最初是D.L Shell於1959所提出,假設要排序的元素有n個,則每次進行插入排序時並不是所有的元素同時進行時,而是取一段間隔。

Shell首先將間隔設定為n/2,然後跳躍進行插入排序,再來將間隔n/4,跳躍進行排序動作,再來間隔設定為n/8、n/16,直到間隔為1之後的最後一次排序終止,由於上一次的排序動作都會將固定間隔內的元素排序好,所以當間隔越來越小時,某些元素位於正確位置的機率越高,因此最後幾次的排序動作將可以大幅減低。

舉個例子來說,假設有一未排序的數字如右:89 12 65 97 61 81 27 2 61 98

數字的總數共有10個,所以第一次我們將間隔設定為10 / 2 = 5,此時我們對間隔為5的數字進行排序,如下所示:
[img]http://caterpillar.onlyfun.net/Gossip/AlgorithmGossip/images/shellSort-1.jpg[/img]
Shell 排序
畫線連結的部份表示 要一起進行排序的部份,再來將間隔設定為5 / 2的商,也就是2,則第二次的插入排序對象如下所示:
[img]http://caterpillar.onlyfun.net/Gossip/AlgorithmGossip/images/shellSort-2.jpg[/img]


再來間隔設定為2 / 2 = 1,此時就是單純的插入排序了,由於大部份的元素都已大致排序過了,所以最後一次的插入排序幾乎沒作什麼排序動作了:
[img]http://caterpillar.onlyfun.net/Gossip/AlgorithmGossip/images/shellSort-3.jpg[/img]


將間隔設定為n / 2是D.L Shell最初所提出,在教科書中使用這個間隔比較好說明,然而Shell排序法的關鍵在於間隔的選定,例如Sedgewick證明選用以下的間隔可以加快Shell排序法的速度:
[img]http://caterpillar.onlyfun.net/Gossip/AlgorithmGossip/images/shellSort-4.jpg[/img]

其中4*(2j)2 + 3*(2j) + 1不可超過元素總數n值,使用上式找出j後代入4*(2j)2 + 3*(2j) + 1求得第一個間隔,然後將2j除以2代入求得第二個間隔,再來依此類推。

後來還有人證明有其它的間隔選定法可以將Shell排序法的速度再加快;另外Shell排序法的概念也可以用來改良氣泡排序法。
public class Sort {
public static void sort(int[] number) {
int gap = number.length / 2;

while(gap > 0) {
for(int k = 0; k < gap; k++) {
for(int i = k+gap; i < number.length; i+=gap) {
for(int j = i - gap; j >= k; j-=gap) {
if(number[j] > number[j+gap]) {
swap(number, j, j+gap);
}
else
break;
}
}
}

gap /= 2;
}
}

private static void swap(int[] number, int i, int j) {
int t = number[i];
number[i] = number[j];
number[j] = t;
}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值