排序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;
}

 运行一下

 

 

posted @ 2019-12-03 20:18  C_hp  阅读(242)  评论(0编辑  收藏  举报