希尔排序
直接插入排序
在正式开始学习希尔排序之前,我们可以先学习他的前身:直接插入排序
直接插入排序算法的具体步骤:
1.在插入第
i
i
i个数时,前
i
−
1
i-1
i−1个数已经排好序
2.将第
i
i
i个数与前
i
−
1
i-1
i−1个数进行比较,从而找到插入位置并插入第
i
i
i个数
3.将插入位置及其后的数依次向后移动
直接插入排序代码(升序排序)
/*将数组data[0]~data[n-1]中的n个整数升序排列*/
void InsertSort(int data[], n) {
for(int i = 1; i < n; i++) {
if(data[i-1] > data[i]) {
int tmp = data[i];
data[i] = data[i-1];
int j;
for(j = i-1; j >= 0 && data[j] > tmp; j--)
data[j+1] = data[j];
data[j+1] = tmp;
}
}
}
手动模拟直接插入排序过程
直接插入排序是一种稳定的排序方法,其时间复杂度为 O ( n 2 ) O(n^2) O(n2),在排序过程中仅需要一个元素的辅助空间,空间复杂度为 O ( 1 ) O(1) O(1)
希尔排序
希尔排序又称为“缩小增量排序”,他是对直接插入排序方法的改进。
希尔排序算法的具体步骤:
1.构造一个步长序列为
d
e
l
t
a
1
,
d
e
l
t
a
2
,
.
.
.
,
d
e
l
t
a
k
delta1, delta2, ..., deltak
delta1,delta2,...,deltak,其中
d
e
l
t
a
1
=
n
/
2
delta1 = n/2
delta1=n/2,后面的每个delta是前一个的
1
/
2
1/2
1/2,
d
e
l
t
a
k
=
1
deltak = 1
deltak=1
2.根据步长序列,进行
k
k
k趟排序
3.对第
i
i
i趟排序,根据对应的步长
d
e
l
t
a
delta
delta,将等步长位置元素分组,对同一组内元素在原位置上进行直接插入排序
希尔排序代码(升序排序)
void ShellSort(int data[], int n) {
int k = n, dk;
int *delta = (int *)malloc(sizeof(int) * (n/2));
for(int i = 0; k >= 1; k /= 2)
delta[i++] = k;
for(int i = 0; (dk = delta[i]) > 0; i++) {
for(k = delta[i]; k < n; k++) {
if(data[k-dk] > data[k]) {
int tmp = data[k]; //备份待插入元素,空出一个元素位置
int j;
for(j = k-dk; j >= 0 && data[j] > tmp; j -= dk)
data[j+dk] = data[j]; //寻找插入位置的同时元素后移动
data[j+dk] = tmp; //找到插入位置,插入元素,取下一个增量值
}
}
}
}
手动模拟希尔排序过程
希尔排序是一种不稳定的排序方法,时间复杂度约为
O
(
n
1.3
)
O(n^{1.3})
O(n1.3),排序过程中仅需要一个元素的辅助空间用于数组元素值的交换,空间复杂度为
O
(
1
)
O(1)
O(1)