排序算法之插入排序

来源:互联网 发布:c语言判断数字大小 编辑:程序博客网 时间:2024/06/10 21:11

一.插入排序基本原理    

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

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更加灵活,它可以提示出错的具体位置,程序也不会马上蹦掉。利于定位错误。

三.测试

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