排序 —— 折半插入排序

一、算法思想

在已形成的有序表中折半查找,并在适当位置插入,把原来位置上的元素向后顺移。


二、算法过程

其中,红色部分是已形成的有序表,黑色部分是待排序元素
在这里插入图片描述


三、实现

void insertSort(int R[],int n)	//待排关键字存储在R[]中,个数为n
{
	int i,j;
	int temp;
	int mid;
	int low;
	int high;
	for(i=1;i<n;i++)	//	由于第一个元素不需要比较,故从第二个元素开始执行插入
	{
		mid;
		low=0;
		high=i-1;	// 0到i-1是已经排序好的部分
		temp=R[i];	// 用于存储待排序的关键字
		while(low<=high)
		{
			mid=(low+high)/2;
			if(temp<R[mid])
				high=mid-1;	//	插入点在低半区
			else
				low=mid+1;	//	插入点在高半区
		}
		for(j=i-1;j>=high+1;j--)	//high+1相当于mid,i-1是已排序序列的最高点,记录后移
		{
			R[j+1]=R[j];
		}
		R[high+1]=temp;	//	插入
	}
}

四、算法性能分析

(1)时间复杂度分析

无论什么情况,外部循环始终逐一执行,外部循环次数为n。

内部循环分为两个部分:一个是折半比较元素的循环,一个是元素移动的循环。

折半插入排序的关键字比较次数和初始序列无关,其折半次数是固定的(都是在low>high时结束),折半次数为 log n。因此,我们要讨论元素移动的时间复杂度。

  • 考虑最坏的情况,即整个序列都是逆序的,则内层循环的元素移动需要逐一执行,因此内部循环次数为 log n + n,故总循环次数为 n( log n + n ),其算法复杂度是 O(n^2)

  • 考虑最好的情况,即整个序列都是顺序的,则内层循环的元素移动不需要执行,因此内部循环次数为 log n + 0,故总循环次数为 n( log n ),其算法复杂度是 O(nlog n)

  • 对于平均的情况,其算法复杂度是 O(n^2)

(2)空间复杂度分析

算法所需要的辅助存储空间不随待排序列的规模的变化而变化,是个常量,因此空间复杂度为 O(1)

(3)稳定性

若两个记录A和B的关键字值相等,A先插入,B后插入,此时排序后A、B的先后次序保持不变,因此称此排序算法是稳定的。

猜你喜欢

转载自blog.csdn.net/starter_____/article/details/93888456