排序算法之插入排序

一.插入排序基本原理    

      对于少量数据的排序,插入排序是个不错的选择,因为他不需要过多额外的空间,也容易理解,使用的频率还是很大。简单的说就是把未排序的数依次插入已排序的系列即可。下面看一个示例:

void InsertSort(int* pnArray, size_t nSize)
{
	int nIndex = 0;

	if(nSize <= 1 || pnArray == NULL)
	{
		return;
	}
	for(nIndex = 1; nIndex < nSize; nIndex++)
	{
		int nTemp = 0;
		int nKeyVal = pnArray[nIndex];

		nTemp = nIndex - 1;
		while(nTemp >= 0 && pnArray[nTemp] > nKeyVal)
		{
			pnArray[nTemp + 1] = pnArray[nTemp];
			nTemp = nTemp - 1;
		}
		pnArray[nTemp + 1] = nKeyVal;
	}
	return;
}
注:该排序为升序。

    假设当前输入序列为一个整形数组:A<31, 41, 59, 26, 41, 58>.。由于当前在26之前序列已经有序了,故插入动作从26才开始,KeyVal此时等于26,26前面一个数也就是59比KeyVal要大故26应该插入到59前面的某个位置,while循环把每个比KeyVal大的数依次向后移动一个位置,最后把nKeyVal插入最后一个比nKeyVal的数前面的位置。以次类推,完成整个排序过程。   

    插入排序比较简单,相信都能很快理解。这里主要说说几个在设计通用函数时候几个需要注意的地方。

二.插入排序优化

     插入排序基于这样一种假设:序列前面k项都已经排序好,这时候插入k+1项,前面k项为升序,因此如果k+1项比k项大,则不需要插入操作。可以得到以下代码:

int InsertSort2(void** ppvArray, size_t nSize, SortCompareFunc CompareFunc)
{
	int nIndex = 0;

	RET_IF_FAIL(nSize > 0 && ppvArray != NULL && CompareFunc!= NULL, -1);
	
	for(nIndex = 1; nIndex < nSize; nIndex++)
	{

		if(CompareFunc(ppvArray[nIndex], ppvArray[nIndex - 1]) < 0)
		{
			void* pvKeyVal = ppvArray[nIndex];
			int nTemp = nIndex - 1;

			while((nTemp >= 0) && (CompareFunc(ppvArray[nTemp], pvKeyVal) > 0))
			{
				ppvArray[nTemp + 1] = ppvArray[nTemp];
				nTemp--;
			}
			ppvArray[nTemp + 1] = pvKeyVal;
		}
	}
	return (0);
}
    和前面讲的冒泡排序类似采用回调函数来抽象隔离变化。

      两个常用的宏:
#define RET_IF_FAIL(p) if(!(p))		\
	{printf("%s\n:%d Warning: "#p" failed. \n",\
		__FILE__, __LINE__); return;}


#define RET_VAL_IF_FAIL(p, ret) if(!(p))		\
	{printf("%s\n:%d Warning: "#p" failed. \n",\
		__FILE__, __LINE__); return(ret);}
上面两个宏比assert更加灵活,它可以提示出错的具体位置,程序也不会马上蹦掉。利于定位错误。

三.测试

     和冒泡排序类似,我们可以用测试模块把该排序函数跑一遍。测试结果:



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值