经典算法之折半插入排序
活动地址:CSDN21天学习挑战赛
前言
再长的路,一步一步也要走完,再短的路,不迈开双脚也无法到达。
折半插入排序
一、什么是折半查找排序
折半插入排序是对插入排序的改进,由于排序算法过程中,就是不断的依次将元素插入前面已拍好序的数列,这样我们不用按照顺序依次寻找插入点,可以采用折半查找的方法来加快寻找插入点的速度。
二、折半插入排序的过程
在将一个新元素插入已排好的数组的过程中,寻找插入点时,将待插入区域的元素设置为a[low],末元素设置为a[high],则每轮比较时将待插入元素与a[m]比较,其中m=(low+high)/2相比较,如果比参考元素小,则选择a[low]到a[m-1]为新的插入区域(即high=m-1),否则选择a[m+1]到a[high]为新的插入区域(即low=m+1),如此直至low<=high不成立,即将此位置之后的所有元素后移一位,并将新元素插入[high+1]。
三、折半插入排序的算法实现
- 输入
n个数的序列,通常直接存放在数组中,可能是任意顺序。
- 输出
输入序列的一个新排列,满足从小到大的顺序(默认讨论升序,简单的修改就可以实现降序排列)。
- 算法说明
每次从原有数据中取出一个数,插入到已排好的序列中,直到所有的数全部取完,那么新的有序排列也就完成了。这个过程与直接插入排序十分类似,不同的地方在于插入时如何寻找位置。该方法采用折半法来快速确定位置。
-
算法流程
1.输入数据被分为有序去和无序区两个部分。 -
最初有序区没有元素,从无序区不断抽取元素放入,保证放入的元素有序
-
一之前i个元素已排好(下标从0至i-1),从无序区取出第一个元素(数据集的第i+1个元素)。
-
先与有序区的最后一个元素比较
a.如果较大则代表该元素已在合适的位置,则直接归入有序区,进入下一个元素的判断。
b.如果较小则需要进一步确定位置,执行以下步骤。 -
搜索区间为从low至high,初始区间为整个有序区(从0至i-1)。
-
将待插入元素记录在临时变量tmp中,为后续的元素串位做准备。
-
计算mid=(low+high)/2,将该位置元素与R[i]比较。
-
不断地缩小搜索区间,直到确定插入位置。
-
确定位置后,将有序区中的元素从后至前逐个后串,最后将tmp中的值覆盖到插入位置。
四、代码如下
#include<iostream>
using namespace std;
const int n = 11;
void SplitSort(int array[], int n);
int main()
{
int array[n] = {0, 4,2,8,0,5,7,1,3,6,9 };
cout << "排序前的数组为:";
for (int i = 1; i < n; i++)
cout << array[i] <<" ";
SplitSort( array,n);
cout << "怕排序后的数组为:";
for (int m = 1; m < n; m++)
{
cout << array[m] << " ";
}
cout << endl;
return 0;
}
void SplitSort(int array[], int n)
{
int i, j, high, low, mid;
for (i = 2 ; i < n; i++)//从第二个元素开始依次将待插入元素后面的数插入到已排好的元素的列表之中
{
array[0] = array[i];
low = 1;
high = i - 1;
while (low <= high)
{
mid = low + (high - low) / 2;;
if (array[mid]>array[0])
{
high = mid - 1;
}
else
{
low = mid + 1;
}
}
for (j = i - 1; j >= high + 1; j--)
{
array[j + 1] = array[j];
}
array[high + 1] = array[0];
}
}