概述:
排序有内部排序和外部排序,内部排序是数据记录在内存中进行排序,而外部排序是因排序的数据很大,一次不能容纳全部的排序记录,在排序过程中需要访问外存。
我们所谓的八大排序就是内部排序。
首先我们学习插入排序,即直接插入排序和希尔排序。
1.直接插入排序
算法思想:把一个数组分为已排序和未排序部分,从未排序部分获取关键字作为待排序数,从已排序部分找到合适位置插入。
要点:设置哨兵,作为临时存储和防止数组下标越界。
直接插入排序图示:
算法实现:
C++ Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
|
#include
void
insertSort(
int
arr[],
int
len) {
int
i, j;
for
(i =
2
; i < len; ++i) { arr[
0
] = arr[i];
for
(j = i -
1
; arr[j] > arr[
0
]; --j) { arr[j +
1
] = arr[j]; } arr[j +
1
] = arr[
0
]; } }
int
main() {
int
arr[] = { -
1
,
55
,
1
,
3
,
11
,
5
,
8
,
6
,
25
,
14
,
47
};
int
len =
sizeof
(arr) /
sizeof
(arr[
0
]); insertSort(arr, len);
return
0
; }
|
稳定性:当遇见一个和插入元素相等的有序序列元素时,插入元素将放到相等元素的后面。因此相等元素的顺序没有改变,原来的顺序就是排序好的顺序,是稳定的。
时间复杂度:由于是两层for循环,因此语句执行次数为(n-2)*(n-3),为O(n^2).
空间复杂度:因只有哨兵位arr[0],所以为O(1)。
2.希尔排序
希尔排序(Shell Sort)是
插入排序
的一种。也称缩小
增量
排序,是直接插入排序算法的一种更高效的改进版本。
算法思想:
先取一个小于n的整数d1作为第一个
增量
,把文件的全部记录分组。所有距离为d1的倍数的记录放在同一个组中。先在各组内进行
直接插入排序
;然后,取第二个增量d2
=1(
<</span>
…
要点: 增量序列的合适选取
C
Code
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
|
|
#include
void
shell(
int
arr[],
int
arr_len,
int
dk) {
int
i, j;
int
tmp;
for
(i = dk; i < arr_len; ++i) { tmp = arr[i];
for
(j = i - dk; j >=
0
&& arr[j] > tmp; j = j - dk) { arr[j + dk] = arr[j]; } arr[j + dk] = tmp; } }
void
shellSort(
int
arr[],
int
arr_len,
int
dka[],
int
dka_len) {
for
(
int
i =
0
; i < dka_len; ++i) { shell(arr, arr_len, dka[i]); } }
int
main() {
int
arr[] = {
55
,
2
,
44
,
6
,
8
,
32
,
46
,
4
,
26
,
24
,
5
,
7
};
int
dka[] = {
5
,
3
,
1
};
int
arr_len =
sizeof
(arr) /
sizeof
(arr[
0
]);
int
dka_len =
sizeof
(dka) /
sizeof
(dka[
0
]); shellSort(arr, arr_len, dka, dka_len);
return
0
; }
|
https://wenku.baidu.com/view/0ffd354bcf84b9d528ea7ae3
.html 借助此参考,我们可以知道SHELL算法的时间复杂度受增量因子序列的影响明t显大于其他因素,选取恰当的增量因子序列能明显提高排序的时间效率。
因此目前还没有人给出选取最好的增量因子序列的方法。增量因子序列可以有各种取法,有取奇数的,也有取质数的。如有人提出,当增量序列为dlta[k]=2^(r-k+1)-1时,希尔排序的时间复杂度为O(n^(3/2)),其中t为排序趟数,k为第几趟排序,1<=k<=t<=log2(n+1)。但需要注意:增量因子中除1 外没有公因子,且最后一个增量因子必须为1。
时间复杂度:其与增量序列的选取有关
空间复杂度:只有临时变量tmp,所以为O(1)。
稳定性:
由于
多次插入排序
,我们知道一次插入排序
是稳定的,不会改变相同元素的相对顺序,但在不同的插入排序
过程中,相同的元素可能在各自的插入排序中移动
,最后其稳定性就会被打乱,所以shell移动
是不稳定的。