Yonker's Blog

码农,程序猿,未来的昏析师

0%

八大排序算法之希尔排序

基本思想

先将整个待排序的记录序列分割成为若干子序列分别进行直接插入排序,待整个序列中的记录“基本有序”时,再对全体记录进行依次直接插入排序。

操作方法

  1. 选择一个增量序列t1,t2,…,tk,其中ti>tj,tk=1;
  2. 按增量序列个数k,对序列进行k趟排序;
  3. 每趟排序,根据对应的增量ti,将待排序列分割成若干长度为m 的子序列,分别对各子表进行直接插入排序。仅增量因子为1 时,整个序列作为一个表来处理,表长度即为整个序列的长度。

算法的实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
package com.zyg.sort;

public class ShellSortAlgorithm
{
// 希尔插入排序
public static void shellInsertSort(int a[], int len, int dk)
{
for (int i = dk; i < len; i++)
{
// 如果第i个元素比它前面的第dk个元素小
<!--more-->
if (a[i] < a[i - dk])
{
int j;
// 记录第i个元素值
int temp = a[i];
// 找到小于第i个元素值的位置,并将其前面元素后移
for (j = i - dk; j >= 0 && a[j] > temp; j = j - dk)
a[j + dk] = a[j];
// 将第i个元素插入到找到的位置
a[j + dk] = temp;
}
}
}

// 希尔排序
public static void shellSort(int a[], int len)
{
// 初始步长为len/2
int dk = len / 2;
while (dk >= 1)
{
// 步长大于1,进行希尔排序
shellInsertSort(a, len, dk);
// 步长减半
dk = dk / 2;
}
}

// 打印数组
public static void printArray(int a[])
{
for (int i = 0; i < a.length; i++)
{
System.out.println(a[i]);
}
}

public static void main(String[] args)
{
// 定义初始化数组
int a[] =
{ 4, 3, 6, 7, 33, 15, 90, 65, 777, 50 };
// 进行希尔排序
shellSort(a, a.length);
// 打印数组
printArray(a);
}
}

效率

时间复杂度

平均情况:O(n1/3)
最好情况:O(n)
最坏情况:O(n2)

空间复杂度

O(1)

稳定性

不稳定