一、预备知识
1、插入排序
二、插入排序改进思路
插入排序由于采用顺序数据结构,插入元素挪动数据无可非议,但是一般的思路是从前向后依次与插入元素进行比较,时间复杂度为O(n),效率非常低。由于数组A[0..i-1]本身是有序的,可以借鉴折半查找的思想寻找插入位置,此时时间复杂度可降为O(lgn).当数据量足够大时,二种排序算法所用的时间相差很大。
三、改进代码实现
//根据二分查找思想获取插入排序元素的插入位置
template<typename T>
int getInsertIndex(T arr[],int index)
{
int firstIndex = 0;
int lastIndex = index - 1;
T key = arr[index];//欲插入元素
//一定是<=,因为分析到只剩下一个元素时,仍需分清胜负,
while (firstIndex <= lastIndex)
{
int midIndex = (firstIndex + lastIndex) >> 1;
if (arr[midIndex] == key)//若中间元素等于插入元素key,
//则应插入到下标为midIndex+1的位置
{
return midIndex+1;
}
else if (arr[midIndex] > key)//若中间元素大于插入元素key,
//则在前半部分寻找插入位置
{
lastIndex = midIndex - 1;
}
else//若中间元素小于插入元素key,则在后半部分寻找插入位置
{
firstIndex = midIndex + 1;
}
}
//arr[0..firstIndex-1] < key,arr[lastIndex+1..index-1]>key
//又firstIndex > lastIndex,故arr[firstIndex]为第一个大于key的元素
//故firstIndex为key应在的位置
return firstIndex;
}
获得每个元素的插入位置后,插入排序算法将非常简单,仅需依次向后移动位置即可。
//折半插入排序
template<typename T>
void binaryInsertSort(T arr[],int length)
{
for (int i=1;i<length;i++)
{
//获取元素arr[i]应在arr[0..i]的位置
int insertIndex = getInsertIndex(arr,i);
T key = arr[i];
//从insertIndex到i,元素依次向后挪动一个
for (int j=i;j>insertIndex;j--)
{
arr[j] = arr[j-1];
}
arr[insertIndex] = key;
}
}