一. 目的
练下算法导论习题,通过二分法查找,快速定位插入位置。
二. 实现代码
实现代码
1、排序代码
//二分法插入排序
void InsertSortVerBinary(T testArray[],int nSize){
LogInfo<T> log = LogInfo<T>();
T key;
log.ShowState("原始数组为:");
log.ShowArray(testArray, nSize);
int nPos(0),j(0);
for (int i = 1; i < nSize; i++){
if (testArray[i] < testArray[i - 1]){
key = testArray[i];
//获取最大可插入位置
nPos = BinarySerch(testArray, i, key);
//元素依次后移
for (j = i - 1; j>=nPos; j--){
testArray[j + 1] = testArray[j];
}
testArray[nPos] = key;
}
}
log.ShowState("最终数组为:");
log.ShowArray(testArray, nSize);
}
2、二分查找代码
//二分法查找位置
int BinarySerch(T testArray[], int nSize,T key){
int nStart(0), nEnd(nSize - 1);
int nMid = (nStart + nEnd) / 2;
while (nStart < nEnd){
if (testArray[nMid]>key){
nEnd = nMid - 1;
}
else if (testArray[nMid] <= key){
nStart = nMid + 1;
}
nMid = (nStart + nEnd) / 2;
}
return key >= testArray[nMid] ? nMid +1: nMid;
}
测试结果
三. 错误
1、二分查找的数组元素个数误写为元素下标上限。
2、对于中间位置是否就是元素应该插入位置,处理不到。如i=Start,i+1=End,此时I位置为中间。在进行下一步,End=Start,只处理上限位置。没有处理下限位置。导致排序出错。
3、对于二分插入排序,理解没到位以为是O(nlogn)复杂度。
四. 经验总结
1、数组使用注意上下标。
2、注意处理边界。另一方面,可以对二分查找进行优化,不用判断边界。如优先判断Start,然后返回Start作为查找位置。将While条件注意处理Start=End的情况。代码如下:
//二分法查找位置
int BinarySerch(T testArray[], int nSize,T key){
int nStart(0), nEnd(nSize - 1);
int nMid = (nStart + nEnd) / 2;
while (nStart <= nEnd){
if (testArray[nMid] <= key){
nStart = nMid + 1;
}
else if (testArray[nMid]>key){
nEnd = nMid - 1;
}
nMid = (nStart + nEnd) / 2;
}
return nStart;
}
3、二分法插入排序与普通排序只是减少了比较时间,仍然为O(n^2)算法复杂度。K个元素时,平均时间算法如下:平均移动位置K/2,查找时间logk,求和为可得到上确界,N*N/4-nlogn,复杂度仍旧为O(N^2).
五. 后续计划
练习给定一个元素,从数组中找出任意两个元素和等于该元素的组合。
六. 参考文献
1、算法导论
2、 二分排序法(折半插入法)http://blog.csdn.net/hopedengxiwang/article/details/6943892