1.直接插入排序
1.排序思路
假设待排序的元素存放在数组
R
[
0..
n
−
1
]
R[0..n-1]
R[0..n−1]中,在排序过程中的某一中间时刻,
R
R
R被划分成为两个子区间
R
[
0..
i
−
1
]
R[0..i-1]
R[0..i−1]和
R
[
i
.
.
n
−
1
]
R[i..n-1]
R[i..n−1],其中前一个子区间是已经排好序的有序区(ordered region),后一个子区间则是当前为排序的部分,不妨设其为无序区(disordered region),初始时i=1,即有序区只有
R
[
0
]
R[0]
R[0]一个元素。
直接插入排序(straight insertion sort)的一趟操作是将当前无序区的开头元素
R
[
i
]
(
1
⩽
i
⩽
n
−
1
)
R[i](1\leqslant i\leqslant n-1)
R[i](1⩽i⩽n−1)插入到有序区
R
[
0..
i
−
1
]
R[0..i-1]
R[0..i−1]中的适当位置,使
R
[
0..
i
]
R[0..i]
R[0..i]变为新的有序区。
那么,对于第i趟排序,如何将无序区的第一个元素
R
[
i
]
R[i]
R[i]插入到有序区呢?
其过程是先将
R
[
i
]
R[i]
R[i]的值存储在临时变量
t
e
m
p
temp
temp中,索引
j
j
j在有序区从后往前找(初值为
i
−
1
i-1
i−1),凡是数组元素值大于temp的,均往后移动一个位置。若找到某个
R
[
j
]
R[j]
R[j],其值小于或等于
t
e
m
p
temp
temp,则将
t
e
m
p
temp
temp放在它们的后面,即置
R
[
j
+
1
]
=
t
e
m
p
R[j+1]=temp
R[j+1]=temp;
具体的过程如下述GIF动图所示:
2.排序算法
void InsertSort(int R[], int n) { //对R[0..n-1]按递增有序进行直接插入排序
int i, j, int temp;
for (int i = 1; i < n; i++) {
if (R[i] < R[i - 1]) {//如果R[i]>=R[i-1] 则保持R[i]的位置不变
temp = R[i];
j = i - 1;
do { //找R[i]的插入位置
R[j + 1] = R[j];
j--;
} while (j >= 0 && R[j] > temp);
R[j + 1] = temp; //在j+1处插入R[i]
}
}
}
3.算法分析
时间复杂度:平均
O
(
n
2
)
O(n^2)
O(n2),最好
O
(
n
)
O(n)
O(n),最差
O
(
n
2
)
O(n^2)
O(n2)
空间复杂度:
O
(
1
)
O(1)
O(1)
稳定性:稳定
2.希尔排序
1.排序思路
希尔排序(shell sort)也是一种插入排序方法,实际上是一种分组插入方法。其基本思想是先取一个小于n的整数
d
1
d_{1}
d1作为第一个增量,把表的全部元素分成
d
1
d_{1}
d1组,将所有距离为
d
1
d_{1}
d1的倍数的元素放在同一个组中。在各组内进行直接插入排序;然后第2个增量
d
2
(
<
d
1
)
d_{2}(<d_{1})
d2(<d1),重复上述的分组和排序,直到所取的增量
d
t
=
1
(
d
t
<
d
t
−
1
⋯
d
2
<
d
1
)
d_{t}=1(d_{t}<d_{t-1}\cdots d_{2}<d_{1})
dt=1(dt<dt−1⋯d2<d1),即所有元素放在同一组中进行直接插入排序为止。
具体过程如下GIF动图所示:
2.排序算法
//希尔排序
void ShellSort(int R[],int n) {
int i, j, d;
int temp;
d = n / 2; //对增量置初值
while (d > 0) {
for (int i = d; i < n; i++) { //对所有组采用直接插入排序
temp = R[i];
j = i - d;
while (j >= 0 && temp < R[j]) {
R[j + d] = R[j];
j = i - d;
}
R[j + d] = temp;
}
d = d / 2;//减小增量
}
}
3.算法分析
时间复杂度:
O
(
n
1.3
)
O(n^{1.3})
O(n1.3)
空间复杂度:
O
(
1
)
O(1)
O(1)
稳定性:不稳定