插入排序
这里总结一下三种插入排序的算法:
- 直接插入排序
- 折半插入排序
- 希尔排序
直接插入排序
直接插入排序是一种最简单的排序方法,它的基本操作就是将一个记录插入到已排好序的有序表中,从而得到一个新的、记录数增1的有序表。
为了在查找插入位置的过程中避免数组下标出界,在r[0]处设置监视哨。
举例:
有一序列为:
i=1: (5) 4 6 8 7 2 3
i=2: (4 5) 6 8 7 2 3
i=3: (4 5 6) 8 7 2 3
i=4: (4 5 6 8) 7 2 3
i=5: (4 5 6 7 8) 2 3
i=6: (2 4 5 6 7 8) 3
i=7: (2 3 4 5 6 7 8)
实现代码如下:
/*
InsertSort Implementation
Author:zzj
Date:17-6-17
*/
#include<cstdio>
using namespace std;
const int maxn = 100;
int a[maxn];
int n;
void InsertSort(int *a)
{
int i,j;
for(i=2; i<=n; i++)
{
if(a[i] < a[i-1]) //需要将a[i]插入有序子表中
{
a[0] = a[i]; //复制为哨兵
a[i] = a[i-1];
for(j=i-2; a[0] < a[j]; j--)
a[j+1] = a[j];//记录后移
a[j+1] = a[0]; //插入到正确位置
}
}
}
int main()
{
scanf("%d", &n);
int i,j;
for(i=1; i<=n; i++){
scanf("%d", &a[i]);
}
InsertSort(a);
for(int i=1; i<=n; i++)
{
printf("%d ", a[i]);
}
return 0;
}
折半插入排序
这里再提供一种减小了比较次数的插入排序算法——折半插入排序,正是利用了插入到有序子表这一特点,有序就可以用二分。
就是找到要插入的位置是通过二分法来查找,这样会减少次数。
/*
BInsertSort Implementation
Author:zzj
Date:17-6-17
*/
#include<cstdio>
using namespace std;
const int maxn = 100;
int a[maxn];
int n;
void BInsertSort(int *a)
{
int low, high, m;
for(int i=2; i<=n; i++)
{
a[0] = a[i]; //将a[i]暂存到a[0]
low = 1, high = i-1;
while(low <= high) //在a[low..high]中折半查找有序插入的位置
{
m = (low + high)/2;
if(a[0] < a[m]) high = m-1;
else low = m+1;
}
for(int j=i-1; j>=high+1; j--) a[j+1] = a[j];//记录后移
a[high+1] = a[0]; //插入
}
}
int main()
{
scanf("%d", &n);
int i,j;
for(i=1; i<=n; i++){
scanf("%d", &a[i]);
}
BInsertSort(a);
for(int i=1; i<=n; i++)
{
printf("%d ", a[i]);
}
return 0;
}
希尔排序
最后再介绍一下这个排序方法。
基本思想是:先将整个待排记录序列分割成若干子序列分别进行直接插入排序,待整个序列中的记录“基本有序”时,再对全体记录进行一次直接插入排序。
举例:
有一序列为:
初始态: 5 4 6 8 7 2 3 增量先是5
第一趟: 2 3 6 8 7 5 4 增量变为3
第二趟: 2 3 5 4 7 6 8 增量变为1
第三趟: 2 3 4 5 6 7 8
/*
ShellSort Implementation
Author:zzj
Date:17-6-17
*/
#include<cstdio>
using namespace std;
const int maxn = 100;
int a[maxn];
int n;
/*
希尔插入排序与直接插入相比,修改了:
1.前后记录位置的增量为dk,而不是1
2.a[0]只是暂存单元,不是哨兵
*/
void ShellInsert(int *a, int dk)
{
int i,j;
for(i=dk+1; i<=n; i++)
{
if(a[i] < a[i-dk]) //需将a[i]插入到有序增量子表
{
a[0] = a[i]; //暂存在a[0]
for(j=i-dk; j>0 && a[0] < a[j]; j-=dk)
a[j+dk] = a[j];//记录后移,查找插入位置
a[j+dk] = a[0]; //插入
}
}
}
/*希尔排序*/
void ShellSort(int *a, int *dlta, int t)
{
for(int i=0; i<t; i++)
{
ShellInsert(a, dlta[i]);//增量逐渐递减为1
}
}
int main()
{
scanf("%d", &n);
int i,j;
for(i=1; i<=n; i++){
scanf("%d", &a[i]);
}
int dt[3] = {5, 3, 1};
ShellSort(a, dt, 3);
for(int i=1; i<=n; i++)
{
printf("%d ", a[i]);
}
return 0;
}