排序2
4.折半插入排序
折半插入排序又称为二分法插入排序,其基本思想为:假设在数据表中有一个元素序列V[0],V[1]....,V[n-1],其中V[0],V[1]....,V[i-1]是已经排序好的元素。在插入V[i]时,利用折半搜索法找到V[i]应该在的位置。
我用图解释一下
数组ar的红色部分是有序的,黑色部分是无序的,现在让low指向有序第一个元素,high指向有序最后一个元素
left指向无序第一个元素,right指向无序最后一个元素
现在只需拿出left指向的元素,在有序序列中找到其应有的位置。
寻找方法为
将left与有序序列中间对比,如果比middle大,则让low指向middle后边的元素
同理,如果比middle小,就让high指向middle前面。
以次循环,这个原理和高数学习的 夹逼法 一样。
实现代码如下
#include<iostream>
using namespace std;
void Binsert(int ar[], int length, const int left, const int right)
{
int temp;
int i, low, high, middle, k;
for(i=left; i<right; ++i)
{
temp = ar[i];
low = 0;
high = i-1;
while(low <= high)
{
middle = (low+high)/2;
if(temp < ar[middle])//比middle指向的元素小,high指向middle前一个元素
high = middle - 1;
else ////比middle指向的元素打,low指向middle后一个元素
low = middle + 1;
}
for(k=i; k>low; --k)
ar[k] = ar[k-1];
ar[low] = temp;
for(int j=0; j<length; ++j)//排一个元素就把整个序列打印
cout<<ar[j]<<" ";
cout<<endl;
}
}
int main()
{
int ar[] = {0,10,15,19,100,1,3,65,9,12,2};
Binsert(ar, sizeof(ar)/sizeof(ar[0]), 5, 9);
return 0;
}
运行结果
当然,当有序序列仅为一个元素时,就相当于对所有元素进行排序了。
函数的right参数可以去掉,因为它就是数组长度,因为我画图了我就不改了。
5.堆排序
堆排序,即依赖堆顶最小(或最大)的特性,反复将堆顶元素取出,然后再对堆进行调整以便下次取出。
程序如下
#include<iostream>
#include"../heap/header.h"
using namespace std;
void HeapSort(int ar[], int length)
{
MinHeap<int, int> heap(ar, length);
for(int i=0; i<length; ++i)
{
int j;
heap.RemoveMin(*&j);
cout<<j<<" ";
}
cout<<endl;
}
int main()
{
int ar[] = {132,5345,1213,36456,323,45765,990,34,2,567,32434};
HeapSort(ar,sizeof(ar)/sizeof(ar[0]));
return 0;
}
运行效果
具体算法解释可见最小堆的 构造函数 与 siftDown函数
https://www.cnblogs.com/area-h-p/p/11977446.html
6.希尔排序
希尔排序又叫做缩小增量排序。该排序的基本思想是:设待排序元素序列有n个元素,首先取一个整数 gap<n 作为间隔,将全部元素分为gap个子序列,所有距离为gap的元素放在同一个子序列中,在每个子序列中分别施行直接插入排序。然后缩小间隔gap,例如取 gap = [gap/2](向下取整),重复上面的子序列划分与排序工作。直到最后gap=1,将所有元素放在一个序列中排序为止。由于开始时gap的取值较大,每个子序列中的元素较少,排序速度较快;待到排序的后期,gap取值逐渐变小,子序列中元素个数逐渐增多,但由于前面的基础工作,大多数元素已经基本有序,所以排序速度仍然很快。
听着有些麻烦哈,用图文来解释一下
ar是要进行希尔排序的序列,第一遍排序时gap = 4,如图所示,只要红线连接的靠后的元素比前面的小,就继续向后走,若靠后元素较大则交换
所以gap=4排序一遍后的ar变成
然后,gap = 2,和上边一样进行排序
排序后结果为
然后,gap=1,
排序完后
这样就把凌乱的数据撸顺啦。
实现代码
#include<iostream>
using namespace std;
void ShellSort(int ar[], const int left, const int right)
{
int i, j, gap = right-left+1;
int temp;
do
{
gap = gap/3 + 1;
for(i=left+gap; i<=right; ++i)
{
if(ar[i-gap] > ar[i])//查看间隔为gap的元素是否前大后小
{
temp = ar[i];//是,则进行交换
j = i-gap;
do
{
ar[j+gap] = ar[j];
j = j-gap;
}while(j>left && temp<ar[j]);
ar[j+gap] = temp;
}
}
cout<<"gap = "<<gap<<", ar = ";
for(int i=0; i<=right; ++i)
cout<<ar[i]<<" ";
cout<<endl;
}while(gap > 1);
}
int main()
{
int ar[] = {535,324,567,2,7587,989,45,234,234545,23534};
ShellSort(ar, 0, 9);
return 0;
}
运行一下