二分查找插入排序(优化的直接插入排序)

直接插入排序

基本思想:将序列分为有序区和无序区,再经过比较和后移操作将无序区元素插入到有序区中。

//C语言直接插入排序
#include <stdio.h>

//升序排列
void insertionSort(int *A,int n) {
    for (int i = 1; i < n; i++) {
        int key = A[i];
        int j = i - 1;
        //线性查找A[i]应插入的正确位置
        while (j >= 0 && A[j] > key) {
            //比key大的都后移一位,给key腾空
            A[j + 1] = A[j];
            j--;
        }
        A[j + 1] = key;
    }
}

main(){
	//测试
    int A[6] = { 4,1,3,2,6,5 };
    insertionSort(A, 6);
    for(int i = 0; i < 6; i++)
        printf("%d ",A[i]);
}

此时考虑对直接插入排序进行优化,原本在有序区查找元素的插入位置时使用的是线性查找法,可以采用二分查找法减少元素比较的次数。


优化:二分查找插入排序

伪代码:

//二分查找,返回A[i]需要插入的位置
BINARY-SEARCH(A,key,low,high)
	while low<=high
		mid=(low+high)/2
		if key<A[mid]
			high=mid-1
		else
			low=mid+1
	return low
	
	
//插入排序
BINARY-INSERTION-SORT(A)
	for i=2 to A.length
		key=A[i]
		loc=BINARY-SEARCH(A,key,1,i)
		for j=i-1 to loc
			A[j+1]=A[j]
		A[loc]=key

C语言实现:

#include <stdio.h>

//二分查找过程,查找key应插入的位置
int binarySearch(int* A, int key, int low, int high) {
    int mid = -1;
    //循环直到low>high,此时low即为要插入的位置
    while (low <= high) {
        mid = (low + high) / 2;
        if (key <= A[mid])
            high = mid - 1;
        else
            low = mid + 1;
    }
    return low;
}

//使用二分查找改进插入排序,使之最坏情况下时间复杂度为Θ(nlgn)
void binInsertionSort(int* A, int n) {
	//在子序列A[0..i]中查找A[i]应插入的位置
    for (int i = 1; i < n; i++) {
        int key = A[i];
        //loc为二分查找获取的A[i]应插入的正确位置
        int loc = binarySearch(A, key, 0, i);
        //如果A[i]的位置需要改变
        if (loc != i) {
        	//loc到i-1位置的元素都往后移动一个位置,把loc位置腾出来
            for (int j = i - 1; j >= loc; j--) {
                A[j + 1] = A[j];
            }
            //把A[i]放到正确的位置
            A[loc] = key;
        }
    }
}

main(){
	//测试
    int A[9] = { 3, 5, 1, 2, 7, 12, 4, 17, 9 };
    binInsertionSort(A, 9);
    for(int i = 0; i < 9; i++)
        printf("%d ",A[i]);
        //输出:1 2 3 4 5 7 9 12 17
}
  • 最好情况(序列为有序)下,无需进行后移操作,排序的时间复杂度为O(lgn)
  • 最坏情况(序列为逆序)下,需要对1 + 2 + 3 + … + (n - 1) = n(n - 1)/2个元素后移,需要的赋值操作次数为n(n - 1)/2 + (n - 1),排序的时间复杂度为O(n2)
  • 平均时间复杂度为O(n2)
  • 5
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值