插入排序
基本思想
在整个数组中找出最小的元素然后和第一个元素进行交换;然后从剩下的元素中找出最小的元素和第二个元素进行交换;以此类推,直到将无需部分全部变成有序为止。
代码
template<typename T>
void insertionSort(T q[], int n) {
for (int i=1; i<n; i++) {
for (int j=i; j>=1; j--)
if(q[j-1] > q[j])
swap(q[j], q[j-1]);
else
break;
}
}
- 优化1, 提前终止内层循环
template<typename T>
void insertionSort(T q[], int n) {
for (int i=1; i<n; i++) {
// 寻找元素arr[i]合适的位置, 和选择排序相比,最大的区别就是该算法可以提前终止内层循环
for (int j=i; j>=1 && q[j-1] > q[j]; j--)
swap(q[j], q[j-1]);
}
}
- 优化2: 将交换操作修改为比较后赋值操作
template<typename T>
void insertionSort(T q[], int n) {
// 寻找元素q[i]合适的插入位置
for (int i=1; i<n; i++) {
// 将待考察的元素赋值一份副本, 然后将它和它前面的元素比较
T e = q[i];
// j保存元素e应该插入的位置
int j;
for (j=i; j>=1 && q[j-1] > e; j--)
// 如果比它前面的元素小, 则更新
// 将交换操作修改为赋值操作
q[j] = q[j-1];
// 将考察的元素放在正确的位置
q[j] = e;
}
}
- 对q[l...r]范围的数组进行插入排序
void insert_sort(int q[], int l, int r) {
for (int i=l+1; i<=r; i++) {
int e = q[i]; // 待考查元素的副本, 用该副本和它前面的元素依次比较
int j; // 待考察元素最终插入的位置
for (j=i; j>=l && q[j-1] < e; j--){
// 如果待考察元素比它前面的元素小, 则说明当前的索引j不是最终插入的位置,需要更新j
q[j] = q[j-1];
}
q[j] = e;
}
}
希尔排序
直接插入排序算法的一种更高效的改进版本。希尔排序是非稳定排序算法。该方法因D.L.Shell于1959年提出而得名。
基本思想
希尔排序是把记录按下标的一定增量分组,对每组使用直接插入排序算法排序;随着增量逐渐减少,每组包含的关键词越来越多,当增量减至1时,整个数组恰被分成一组,算法便终止。
代码
template<typename T>
void shellSort(T q[], int n) {
int h = 1;
while(h < n/3)
h = h*3 + 1;
while(h >= 1) {
// h-sort the array
for (int i=h; i<n; i++) {
T e = q[i];
int j;
// 对q[i], q[i-h], q[i-2*h]....进行插入排序
for (j=i; j>=h && q[j-h] > e; j -= h)
q[j] = q[j-h];
q[j] = e;
}
h /= 3;
}
}
- 对q[l...r]范围的数组进行希尔排序
// 修改插入排序, 传入增量h
template<typename T>
void insertionSort(T q[], int l, int r, int h) {
for (int i=l+h; i<=r; i++) {
T e = q[i];
// j保存元素e应该插入的位置
int j;
// 对 q[i], q[i-h], q[i-2*h], q[i-3*h]... 使用插入排序
for (j=i; j>=l+h && q[j-h] > e; j-=h)
q[j] = q[j-h];
q[j] = e;
}
return;
}
template<typename T>
void shellSort(T q[], int l, int r) {
/* Knuth序列: 唐纳德, 以为图灵奖获得者发明的序列
h=1
h=3*h+1 */
// 计算 increment sequence: 1, 4, 13, 40, 121, 364, 1093...
int h = 1;
while( h < (r-l+1)/3 )
h = 3 * h + 1;
while(h>=1) {
// h-sort the array
insertionSort(q, l, r, h);
h /= 3;
}
}
优化: 使用Knuth序列
/* Knuth序列: 唐纳德, 以为图灵奖获得者发明的序列 h=1; h=3*h+1 */ // 计算 increment sequence: 1, 4, 13, 40, 121, 364, 1093... int h = 1; while( h < (r-l+1)/3 ) h = 3 * h + 1;
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。