插入排序
对象:一条杂乱无章的数组
实现:从小到大。
在说希尔排序之前,先说说简单插入排序:
1.简单插入排序:
- 简单插入排序的核心思想:把一条这么个难看的序列默认分为两个排好序的和未排好序的两个部分;所以一开始排好序的只有一个a[0](好看的只有一个),难看的有N(数组长度)-1个a[1,n-1];然后呢,你就要顺序下来,把一个个难看的几个人插到好看的那一堆里去,好看的越来越多,难看的越来越少,最后变成了真的好看的;
- 简单排序插入的代码:
void InsertionSort(int a[],int n) //a[]是要处理的数组,n是数组长度
{
int i,j;
int temp;
//默认就是两部分,一部分好看,一部分难看;
//把难看的解决就好了
for(i=1;i<=n-1;i++) //有n-1个难看的
{
temp=a[i];
for(j=i-1;j>=0;j--)
{
if(a[j]<temp) //这个难看孩子在好看的位置,就是前面那个比他小的时候
break;
a[j+1]=a[j];
}
a[j+1]=temp; //比他小的好看孩子的后面一个啊;就算最小的还比他大,j传出来会变成-1,j+1就是0了
}
Check(a,n);
}
2.希尔排序:
前言:
我们能看到简单插入排序之所以效率不高是每次只交换两个元素,这样只消去一对错位的元素。
所以,希尔排序在这个方面做了一些改进,我能不能一下子交换一堆啊?
希尔排序的基本原理:
将待排序的一组元素按一定间隔分成若干个序列,分别进行插入排序。
开始的时候间隔较大,在每轮排序过程中间隔会变小,直至间隔变成“1”,
这也是最后进行简单的插入排序。
试问:这样一定能排好么?
其实是一定的啊,因为在比较的过程中,小的一直在往前面提,而且在增量大的情况下是大步向前提,每次排序好再选取下一个增量,直至最后一个增量啊(一般情况下就是1)
所以比如这么一个序列:
10
44 12 59 36 62 43 94 7 35 52 85
我们初始设置增量为5:
那么我们是不是能理解成:
{44(数组0位置),43(数组0位置+5),85(数组0位置+5+5)}这就是一个子序列。因为他们是一类在比较;
所以同样的有:
序列{12(1位置),94(1位置+5)},序列{59,7},序列{36,35},序列{62,52}都是。他们在各自的一类,如果存在错位就进行交换。
在上面增量为5排序后就是:
43 12 7 35 52 44 94 59 36 62 85
代码:
void Check(int a[], int n)
{
int i;
for(i=0;i<n;i++)
printf("%3d",a[i]);
puts("");
}
//a[]是待排序的数组,数组长度为n;
//incre[]为增量的序列,数组长度m个,最后一个元素是1.
void ShellSort(int a[], int incre[],int m,int n)
{
int i,j,k,incerement;
int temp;
for(i=0;i<m;i++)
{
incerement=incre[i];//需要这趟排序的增量
for(j=incerement;j<n;j++)
{
temp=a[j]; //待排元素
for(k=j;k-incerement>=0;k-=incerement)
{
if(temp>=a[k-incerement])
break;
else
a[k]=a[k-incerement];
}
a[k]=temp;
}
Check(a,n);//看看这个数组咋变的:
}
}
//附数据:含10个待排序的元素;含4个增量数组元素
10 4
44 12 59 36 62 43 94 7 35 52 85
5 3 2 1
总结:
希尔排序只需要O(1)的额外空间;
希尔排序最差的时间复杂度是O(N^2);
希尔排序不是稳定的排序方法;