【插入排序】折半插入排序

折半插入排序(Binary Insertion Sort) 

    直接插入排序采用顺序查找法查找当前记录在已排好序的序列中插入位置,这个“查找”操作可利用“折半查找”来实现,由此进行的插入排序称之为折半插入排序(Binary Insertion Sort)。

[算法思想]

1)将待排序的记录存放在数组r[1..n]中,r[1]是一个有序序列。

2)循环n-1次,每次使用折半查找法,查找r[i]插入表长为i-1的有序序列r[1..i-1],直到将r[n]插入表长为n-1的有序序列r[1..n-1],最后得到一个表长为n的的有序序列。

[算法描述]

void BInsertSort(int r[],int Length)
{
	/* 对顺序表r做折半插入排序 */
	for(int i = 2;i < Length;i++)
	{
		r[0] = r[i];                    /* 将待插入的记录暂存到监视哨中 */
		int low = 1;int high = i-1;     /* 置查找区间初值 */
		while(low <= high)              /* 在r[low..high]中折半查找插入的位置 */ 
		{ 
			int m = (low+high)/2;       /* 折半 */
			if(r[0] < r[m]) high = m-1; /* 插入点在前一子表 */
			else low = m+1;             /* 插入点在后一子表 */
		}
		for(int j = i-1;j >= high+1;--j) r[j+1] = r[j];  /* j记录后移 */
		r[high+1] = r[0];               /* 将r[0]即原r[i],插入到正确位置 */
	}
}

[算法分析]

1.时间复杂度

     从时间上比较,折半查找比顺序查找块,所以就平均性能来说,折半插入排序优于直接插入排序。

     折半插入排序所需要的关键字比较次数与待排序序列的初始排列无关,仅依赖于记录的个数。不论初始序列情况如何,在插入第i个记录时,需要经过log2i+1次比较,才能确定它应插入的位置。所以当记录的初始排序为正序或接近正序时,直接插入排序比折半插入排序执行的关键字比较次数要少。

     折半插入排序的对象移动次数与直接插入排序相同,依赖于对象的初始排列。在平均情况下,折半插入排序仅减少了关键字间的比较次数,而记录的移动次数不变。因此,折半插入排序的时间复杂度仍为(n^2)。 

2.空间复杂度

   折半插入排序所需附加存储空间和直接插入排序相同,只需要一个记录的辅助空间r[0],所以空间复杂度为O(1)。

[算法特点]

1)是稳点排序。

2)因为要进行折半查找,所以只能用于顺序结构,不能用于链式结构。

3)适合初始记录无序、n较大时的情况。   

[完整代码]

#include
using namespace std;
void BInsertSort(int r[],int Length)
{
	/* 对顺序表r做折半插入排序 */
	for(int i = 2;i < Length;i++)
	{
		r[0] = r[i];                    /* 将待插入的记录暂存到监视哨中 */
		int low = 1;int high = i-1;     /* 置查找区间初值 */
		while(low <= high)              /* 在r[low..high]中折半查找插入的位置 */ 
		{ 
			int m = (low+high)/2;       /* 折半 */
			if(r[0] < r[m]) high = m-1; /* 插入点在前一子表 */
			else low = m+1;             /* 插入点在后一子表 */
		}
		for(int j = i-1;j >= high+1;--j) r[j+1] = r[j];  /* j记录后移 */
		r[high+1] = r[0];               /* 将r[0]即原r[i],插入到正确位置 */
	}
}
int main()
{
	int a[11]={0,1,0,2,3,9,8,7,4,5,6}; /* 注意,a[0]为监视哨 */
	BInsertSort(a,11);
	for(int i=1;i<11;i++)
		cout<

[运行结果]
【插入排序】折半插入排序_第1张图片


你可能感兴趣的:(【数据结构】笔记)