插入排序改进-折半插入排序

一、预备知识

       1、插入排序

       2、折半查找(二分查找)

二、插入排序改进思路

       插入排序由于采用顺序数据结构,插入元素挪动数据无可非议,但是一般的思路是从前向后依次与插入元素进行比较,时间复杂度为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;
    }
}


你可能感兴趣的:(数据结构,算法)