直接插入排序指的是先将一小部分排好序,然后从未排序的元素中找一个出来.遍历已排序好的数组,插入到合适位置.
直接插入排序:
void StraightInsertSort(int* arr, int len)
{
int tmp;
int j;
for(int i = 1; i < len; i++)
{
tmp = arr[i];
for(j = i-1; j >=0 ; j --) //遍历已经排好序的部分,找到合适的位置j + 1
{
if( arr[j] >= tmp)
break;
}
for(int k = i; k > j + 1; k--) //把位置j + 1后面的元素右移
{
arr[k] = arr[k -1];
}
arr[j + 1] = tmp; //插入元素到位置j+1
}
}
我们看到在从已经排好序的数组中找合适的位置的时候可以改进一下,用下二分查找的方法.
改进的插入排序算法:
void BinaryInsertSort(int* arr, int len)
{
int tmp;
int j;
for(int i = 1; i < len; i++)
{
tmp = arr[i];
int left = 0;
int right = i - 1;
while(left <= right) //通过二分查找找到合适的插入位置
{
int mid = (left + right)/2;
if( tmp == arr[mid])
{
j = mid;
break;
}
else if( tmp < arr[mid])
right = mid -1;
else if( tmp > arr[mid])
left = mid + 1;
}
if(left > right)
j = left - 1;
for(int k = i; k > j + 1; k--) //把位置j + 1后面的元素右移
{
arr[k] = arr[k -1];
}
arr[j + 1] = tmp; //插入元素到位置j+1
}
}
希尔排序(shell sort)
当数组中的元素基本有序的时候采用直接插入排序效率非常高,根据这个思路产生了一个改进的插入排序算法,希尔排序.
大体思路是先把整个待排序元素序列分割成若干子序列(由相隔的增量组成)分别采用直接插入排序,这样每排一次元素就变得更有序,然后增量缩小再接着重复上面的操作.
比如按增量5,3,1,0分别进行插入排序.当增量是1时就相当于对整个数组采取直接插入排序了.
你可能会好奇这个增量是怎么确定的? 这就存在很多不同的方法了,一般用的较多较容易的就是直接用数组长度n除以2,然后把结果继续除2.
void ShellSort(int* arr, int len)
{
for( int gap = len/2;gap > 0; gap = gap/2) //通过不同的增量来使数组一步步达到更有序的状态
for( int i = 0; i < gap; i ++)
{
for(int j = i + gap; j < len; j = j + gap) //对每个增量产生的子序列进行插入排序
if( arr[j] < arr[j - gap])
{
int tmp =arr[j];
int k ;
for( k = j - gap; k >= 0; k = k - gap)
{
if( tmp < arr[k])
arr[k + gap] = arr[k];
else
break;
}
arr[ k +gap] = tmp;
}
}
}