直接插入排序+优化+二分查找

插入排序:

        插入排序的原理就是当前位置的元素值大于后进来元素值,就进行交换。

排序过程如下:

         10 3 26 9 30 15 18 211

                 3 10 26 9 30 15 18 211 

                 3 10 26 9 30 15 18 211 

                 3 10 26 9 30 15 18 211

                 3 9 10 26 30 15 18 211

                 3 9 10 26 30 15 18 211

                 3 9 10 15 26 30 18 211

                 3 9 10 15 18 26 30 211

                 3 9 10 15 18 26 30 211

代码实现:

#include<stdio.h>

void InsertSort(int arr[],int nLength)
{        //日常检测
	if(arr == NULL || nLength <=0)return;
	
	int i;
	int j;
	int temp;

	for(i = 1;i<nLength;i++)
	{
		j = i-1; //有序的最后一个
		temp = arr[i]; //无序第一个元素

		//找到无序元素所在位置
		while(arr[j] > temp && j>=0)
		{
			arr[j+1] = arr[j];
			j--;
		}
		//值放入
		arr[j+1] = temp;
	}
}

void Print(int arr[],int nLength)
{
	int i;
	for(i = 0;i<nLength;i++)
	{
		printf("%d ",arr[i]);
	}
	printf("\n");
}

int main()
{
	int arr[] = {10,3,26,9,30,15,18,211};
	InsertSort(arr,sizeof(arr)/sizeof(arr[0]));
	Print(arr,sizeof(arr)/sizeof(arr[0]));
	return 0;
}
效果展示:

复杂度与稳定性:

插入排序的平均时间复杂度是O(n^2),最好情况是O(n),最差情况是O(n^2),是一种稳定的排序方法,空间复杂度是O(1)。备注:大部分已排序好时较好使用。

算法优化:

1.设置哨兵位:

    哨兵的插入排序中的哨兵元素有两个作用:
        1、暂时存放待插入的元素

        2、防止数组下标越界,当待插入的元素小于已排序的子数组中的最小元素时,j=-1,越界,而采用哨兵,arr[0]<arr[j],当j=0时,就结束循环,不会出现越界。   

for(i = 1;i<nLength;i++)
	{
		j = i-1; //有序的最后一个
		temp = arr[i]; //无序第一个元素
                arr[0] = temp;//设置哨兵位
		//找到无序元素所在位置
		while(arr[j] > temp)
		{
			arr[j+1] = arr[j];
			j--;
		}
		//值放入
		arr[j+1] = temp;
	}

        2.使用二分排序法:

        查找过程是:在有序表中,取中间的记录作为比较关键字,若给定值与中间记录的关键字相等,则查找成功;若给定的值小于中间记录的关键字,则在中间记录的左半区间继续查找;若给定值大于中间记录的关键字,则在中间记录的右半区间继续查找;不断重复这个过程,直到查找成功。否则查找失败。

#include<iostream>
using namespace std;
int Binarysearch(int arr[],int item,int low,int high)
{
	if(high<=low) return (item>=arr[low])?(low+1):low;

	int mid = low+(high-low)/2;

	if(item == arr[mid]) return mid;
	if(item > arr[mid])
		return Binarysearch(arr,item,mid+1,high);
	else //item< mid
	return Binarysearch(arr,item,low,mid-1);
}
void InsertSort(int arr[],int nLength)
{
	if(arr == NULL || nLength <=0)return;
	
	int i;
	int j;
	int temp;
	int k;
	for(i = 1;i<nLength;i++)
	{
		j = i-1; //有序的最后一个
		temp = arr[i]; //无序第一个元素
		k = Binarysearch(arr,temp,0,j);
		//找到无序元素所在位置
		while(j >= k )
		{
			arr[j+1] = arr[j];
			j--;
		}

		//值放入
		arr[j+1] = temp;
	}
}

void Print(int arr[],int nLength)
{
	int i;
	for(i = 0;i<nLength;i++)
	{
		printf("%d ",arr[i]);
	}
	printf("\n");
}

int main()
{
	int arr[] = {10,3,26,9,30,15,18,211};
	cout<<"原来的:";
	Print(arr,sizeof(arr)/sizeof(arr[0]));
	cout<<"现在的:";
	InsertSort(arr,sizeof(arr)/sizeof(arr[0]));
	Print(arr,sizeof(arr)/sizeof(arr[0]));
	system("pause");
	return 0;
}


复杂度与稳定性:

        插入排序一般情况下复杂度时O(n^2),最差情况下复杂度是O(n^2);最好情况是O(n),空间复杂度是O(1),是一种稳定的算法。

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值