排序算法:选择排序、插入排序、希尔排序、归并排序、快速排序

6 篇文章 0 订阅
1 篇文章 0 订阅

c++STL里面是有排序接口的,不过还是想学习一下经典的排序算法。我没有使用模板类来实现,而是指定了整形数组。

上代码,方便以后看:

***.h

#pragma once
#include <iostream>
#include <vector>
using namespace std;
class MySort
{
public:
	MySort();
	~MySort();

	/*初级排序*/
	void SelectSort(vector<int> &a);
	void InsertSort(vector<int> &a);
	/*改进初级排序*/
	void ShellQuickSort(vector<int>& a);
	void ShellQuickSort(vector<int>& a,bool (*P_less)(int &x,int &y));
	/*归并排序-渐进最优(最坏情况与最好情况下的时间复杂度一致)*/
	void MergeQuickSort(vector<int>& a);
	void MergeQuickSort(vector<int>& a,int low,int high);
	/*快速排序*/
	/*基本快排*/
	void QuickSort(vector<int>& a);
	void QuickSort(vector<int>&a,int low,int high);
	/*改进快排*/

private:
	void exchan(vector<int> &a, int j, int k);
	bool less(int &x,int &y);
	void merge(vector<int> &a, int low, int mid, int high);
	int partition(vector<int> &a,int low, int high);

	vector<int> aux;

};

***.cpp

#include "MySort.h"

MySort::MySort()
{
}


MySort::~MySort()
{
}
/*======================选择排序==========================
		选择排序:
		选择最小的放在左端
		原地排序算法;基本排序算法;
*/
void MySort::SelectSort(vector<int>& a)
{
	int N = a.size();
	int tmp;
	int min;
	for (int i = 0; i < N; i++) {
		min = i;
		for (int j = i + 1; j < N; j++) {
			if (less(a[j], a[i]))
				min = j;
		}
		exchan(a, i, min);
	}
}
/*========================插入排序==========================
		插入排序:
		遍历到某一位元素,就将该元素左侧排序
		原地排序算法;基本排序算法;
*/
void MySort::InsertSort(vector<int>& a)
{
	int N = a.size();
	for (int i = 0; i < N-1;i++) {
		for (int j = i + 1; j >= 0;j--) {
			if (less(a[j], a[j - 1]))
				exchan(a,j,j-1);
		}
	}
}


/*===========================希尔排序shell-sort=========================
	改进了插入排序:
	插入排序适合小规模和部分有序的数据进行排序,
	希尔排序再进行h=1的排序之前的操作就是将原始数据进行部分排序;
	原地排序算法;改进的基本排序算法;
	时间复杂度:不确定
*/
void MySort::ShellQuickSort(vector<int>& a)
{
	int N = a.size();
	int h = 1;
	while (h < N / 3)
		h = 3 * h + 1;//1,4,13,40,121,364……h的初始值。例如h=13,那么第一次做13-有序,4-有序,1-有序
	while (h >= 1) {
		//将数组变为h有序
		for (int i = h; i < N; i++) {
			for (int j = i; j >= h && less(a[j], a[j - h]); j -= h) {
				exchan(a,j,j-h);
			}
		}
		h = h / 3;
	}
}
/*重载一个可以自定义比较方法的希尔排序*/
void MySort::ShellQuickSort(vector<int>& a, bool(*P_less)(int &x, int &y))
{
	int N = a.size();
	int h = 1;
	while (h < N / 3)
		h = 3 * h + 1;
	while (h >= 1) {
		//将数组变为h有序
		for (int i = h; i < N; i++) {
			for (int j = i; j >= h && (*P_less)(a[j], a[j - h]); j -= h) {
				exchan(a, j, j - h);
			}
		}
		h = h / 3;
	}
}
/*=================================归并排序================================
	归并排序:拆分原序列,对两条子序列先排序后归并;子序列排序:递归调用
	此处实现了自顶向下的归并排序,因为使用递归,应该不适合超长序列,以免爆栈
	原地归并排序,额外空间为常数;
	时间复杂度:~Nlog(N),渐进最优的基于比较的排序算法
	空间复杂度:不是最优
*/
void MySort::MergeQuickSort(vector<int>& a)
{
	aux.assign(a.begin(),a.end());
	MergeQuickSort(a,0,a.size()-1);
}

void MySort::MergeQuickSort(vector<int>& a, int low, int high)
{
	if (high <= low) return;
	int mid = low + (high - low) / 2;
	MergeQuickSort(a, low, mid);
	MergeQuickSort(a, mid + 1, high);
	merge(a,low,mid,high);
}
/*=================================快速排序=================================
	快速排序:寻找切分点,切分点是归位元素,递归寻找子序列切分点
	快速排序是一个自底向上的排序,迭代最外层是有序的起点,这与归并排序是相反的
	时间复杂度优于归并排序和插入排序
	归并排序和快速排序都体现了分治的思想,并且递归过程十分相似
*/
void MySort::QuickSort(vector<int>& a)
{
	//打乱顺序省略
	QuickSort(a,0,a.size()-1);
}
void MySort::QuickSort(vector<int>& a, int low, int high)
{
	if (low >= high) return;
	int j = partition(a,low,high);//寻找并归位切分点
	QuickSort(a,low,j-1);
	QuickSort(a,j+1,high);
}
/*======================================PRIVATE===================================*/
void MySort::exchan(vector<int> &a, int j, int k)
{
	int tmp;
	tmp = a[j];
	a[j] = a[k];
	a[k] = tmp;
}

bool MySort::less(int &x, int &y)
{
	if (x <= y)
		return true;
	return false;
}
/*===========================归并算法===============================
	归并算法:
	 本工程中专门为归并排序调用,设为私有成员;
	 合并原序列的两条有序子序列;
	 原地归并;
*/
void MySort::merge(vector<int>& a, int low, int mid, int high)
{
	int i = low;
	int j = mid + 1;
	for (int k = low; k <= high; k++) {
		aux[k] = a[k];
	}
	for (int k = low; k <= high;k++) {
		if (i > mid)
			a[k] = aux[j++];
		else if (j > high)
			a[k] = aux[i++];
		else if (less(aux[i], aux[j]))
			a[k] = aux[i++];
		else 
			a[k] = aux[j++];
	}
}
/*=========================切分算法=================================
	切分算法:
	切分的过程就是随即确定一个切分点,然后移动左右哨兵
	使得左哨兵不大于切分点,右哨兵不小于切分点
	如果先移动的是左哨兵,那么左右哨兵碰撞的时候一定是右哨兵碰撞左哨兵,此时
	需要交换切分值与右哨兵的元素,完成切分值归位,并返回右哨兵
*/
int MySort::partition(vector<int>& a, int low, int high)
{
	int i = low;
	int j = high + 1;
	int val = a[low];
	while (1) {
		while (less(a[++i], val))
			if (i == high)
				break;
		while (less(val, a[--j]))
			if (j == low)
				break;
		if (i >= j)
			break;
		exchan(a,i,j);
	}
	exchan(a,low,j);
	return j;
}

测试结果:

使用50000个随机数,慢的排序会导致应用线程直接退出,所以先比较速度比较快地三个排序:希尔排序、归并排序、快速排序

#if SORT_TEST
	MySort sortAPI;
	vector<int> v_0;
	for (int i = 0; i < 50000; i++) {
		v_0.push_back(rand());
	}
	vector<int> v_1 = v_0;
	vector<int> v_2 = v_0;
	vector<int> v_3 = v_0;
	vector<int> v_4 = v_0;

	DWORD start;
	//start = GetTickCount();
	//sortAPI.InsertSort(v_0);
	//cout << (GetTickCount() - start) << endl;

	//start = GetTickCount();
	//sortAPI.SelectSort(v_1);
	//cout << (GetTickCount() - start) << endl;

	start = GetTickCount();
	sortAPI.ShellQuickSort(v_0);
	cout << (GetTickCount() - start) << endl;

	start = GetTickCount();
	sortAPI.MergeQuickSort(v_1);
	cout << (GetTickCount() - start) << endl;

	start = GetTickCount();
	sortAPI.QuickSort(v_2);
	cout << (GetTickCount() - start) << endl;
#endif

两个比较慢的排序:选择排序,插入排序,500个随机数

对于随机数的排序效率:插入排序<选择排序<希尔排序<归并排序<快速排序

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值