排序算法大集合
源代码如下
类的定义
#pragma once
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
class Sort {
public:
/*
*选择排序:首先找到数组中最小的数,其次,将他和数组中的第一个元素交换位置
*
*再次,在剩下的元素中找到最小的元素,将他与数组中的第二个元素交换位置。如此往复。
*因此叫做选择排序。
*
*@author qls
*@date 2018 7-31 下午16:15
*
*/
void select_sort(vector<int> & arr);
/**
*
*插入排序:通常人们整理桥牌的方法是一张张的来,将每一张牌插入到其他已经有序的牌
*的适当位置。在计算机的实现中,这种算法叫做 插入排序
*
*@author qls
*@date 2018 7-31 下午16:31
*
**/
void insert_sort(vector<int> &arr);
/**
*希尔排序是一种基于插入排序的快速排序算法。
*对于大规模乱序数组插入排序很慢,因为他只会交换相邻的元素
*因此元素只能一点一点的从数组的一端移动到另一端。
*
*希尔排序为了加快速度简单的改进插入排序,交换不相邻的元素
*以对数组的局部进行排序,最终用插入排序将局部有序的数组排序
********************************************
*希尔排序的思想是使数组中任意间隔为h的元素都是有序的。这样的数组
*称为h有序数组。
*一个h有序数组就是h个相互独立的有序数组编制在一起形成的一个数组
*希尔排序需要利用递增序列,这是核心思想。希尔排序的递增序列必须互质。
*********************************************
*实现希尔排序的一种方法是对于每个h,用插入排序将h个子数组独立排序。
*
*@author qls
*@date 2018 7-31 下午17:21
*
*/
void shell_sort(vector<int> &arr);
/**
*归并排序
*将一个数组递归的分成两半分别排序,然后将结果归并起来
*归并排序的缺点是是其需要的额外的空间和任意长度的N成正比
*
*@author qls
*@date 2018 8-1 上午午10:35
*/
void guibin_sort(vector<int> &res);
/**
*快速排序是一种分治的排序算法。它将一个数组分成两个子数组
*将两部分独立的排序。快排和归并排序是互补的:
*归并排序将数组分成两个子数组分别排序,并将有序的子数组归并并以将整个
*数组排序;而快速排序将数组排序的方式则是当两个数组都有序
*时整个数组也就自然有序了。在第一种情况中,递归调用发生在处理整个数组
*z之前;在第二种情况中,递归调用发生在处理整个数组之后。
*在归并排序中,一个数组被等分为两半;在快速排序中,切分(partition)
*的位置取决于数组的内容。
*
*
*@author qls
*@date 2018 8-1 下午15:35
*/
void quick_sort(vector<int> &res);
/**
*二叉堆是一个数组,其可以被看成一个近似的完全二叉树。
*二叉堆分为两种情况:最大堆和最小堆。
*在最大堆中,最大堆性质是指除了根以外的所有节点都满足A[parent]>=A[i]
*即某个节点的值至多与其父节点一样大。
*在堆排序算法中一般使用最大堆,而优先队列一般使用最小堆。
*
*@author qls
*@date 2018 8-2 下午16:28
**/
void Heap_sort(vector<int> &res);
void sort_out(vector<int> &arr);
private:
void gb_sort(vector<int> &res,int L,int R); //归并排序接口
void merge(vector<int> &res,int L,int mid,int R);//归并
void quicksort(vector<int> &res,int L,int R);//快速排序
int partition(vector<int> &res,int L,int R);//快排分化
void max_heap(vector<int> &res,int i,int heap_size); //用于维持最大堆
void build_heap(vector<int> &res); //创建最大堆
void Heapsort(vector<int>&res);//堆排序
};
实现如下
#include "Sort.h"
void Sort::select_sort(vector<int>& arr)
{
for (int i = 0;i < arr.size() - 1;++i) {
auto beg=min_element(arr.begin()+i,arr.end());
swap(arr[i],*beg);
}
}
void Sort::insert_sort(vector<int>& arr)
{
for (int i = 1;i < arr.size();++i) {
int p=i-1; //已经插入的排好序的最大下标
int temp=arr[i];
while (p >= 0 && arr[p] > temp) {
arr[p+1]=arr[p];
p--;
}
arr[p+1]=temp;
}
}
void Sort::shell_sort(vector<int>& arr)
{
//升序排列
int N=arr.size();
int h=1; //递增序列
while(h<N/3) h=3*h+1;
while (h >= 1) {
//将数组变为h有序
for (int i = h;i < N;++i) {
//将arr[i]插入到arr[i-h],arr[i-2h],arr[i-3h].....之中
for (int j = i;j >= h && (arr[j] < arr[j - h]);j -= h) {
swap(arr[j],arr[j-h]);
}
}
h/=3;
}
}
void Sort::guibin_sort(vector<int>& res)
{
gb_sort(res,0,res.size()-1);
}
void Sort::quick_sort(vector<int>& res)
{
quicksort(res,0,res.size()-1);
}
void Sort::Heap_sort(vector<int>& res)
{
Heapsort(res);
}
void Sort::sort_out(vector<int>& arr)
{
for (auto &c : arr) {
cout<<c<<" ";
}
cout<<endl;
}
void Sort::gb_sort(vector<int>& res, int L, int R)
{
if (L < R) {
int mid=(L+R)/2; //归并
gb_sort(res,L,mid);
gb_sort(res,mid+1,R);
merge(res,L,mid,R);
}
return;
}
void Sort::merge(vector<int>& res, int L, int mid, int R)
{
int left=mid+1-L;
int right=R-mid;
vector<int> La(left);
vector<int> Ra(right); //生成两个辅助数组
/*
*将相对应的值复制到指定数组中
*/
for (int i = 0;i < left;++i) {
La[i]=res[i+L];
}
for (int j = 0;j < right;++j) {
Ra[j]=res[mid+1+j];
}
/**
*归并
**/
int i =0,j=0;
int k=L;
while (i < left&&j < right) {
if (La[i] <= Ra[j]) {
res[k]=La[i];
++i;
}
else {
res[k]=Ra[j];
++j;
}
++k;
}
while (i < left) {
res[k] = La[i];
++i;
++k;
}
while (j < right) {
res[k] = Ra[j];
++j;
++k;
}
/*
for (int k = L;k <= R;++k)
{
if (i<left&&j<right&&La[i] <= Ra[j])
{
res[k] = La[i];
++i;
}
else if (j<right&&i<left&&La[i] > Ra[j])
{
res[k] = Ra[j];
++j;
}
else if (i < left)
{
res[k] = La[i];
++i;
}
else if (j< right)
{
res[k] = Ra[j];
++j;
}
}*/
}
void Sort::quicksort(vector<int>& res, int L, int R)
{
if (L < R) {
int p=partition(res,L,R);
quicksort(res,L,p-1);
quicksort(res,p+1,R);
}
}
int Sort::partition(vector<int>& res, int L, int R)
{
int p=L-1;
int value=res[R];
for (int k = L;k <= R;++k) {
if (res[k] <=value) {
++p;
swap(res[k],res[p]); //将小于value的值,放在前半部分
}
}
swap(res[p+1],res[R]); //交换两个值
return p+1;
}
/**
* 维持最大堆的策略叫做 下滤。
**/
void Sort::max_heap(vector<int>& res, int i,int heap_size)
{
int lastE=res[i];
int parent=i; //最大堆的根节点
int child ;
for (;2 * parent+1 <=heap_size;parent = child) {
child=2*parent+1;
if (child != heap_size && res[child + 1] > res[child]) {
/*由于将每一个节点看做有两个儿子,因此利用child!=res.size(),进行判断
*res[child + 1] > res[child]此时右儿子比左儿子大
*选择右儿子
*/
child++;
}
if (lastE >res[child]) {
break;
}
else {
res[parent] = res[child];
}
}
res[parent]=lastE;
}
void Sort::build_heap(vector<int>& res)
{
for (int parent = res.size() / 2;parent >= 0;--parent) {
max_heap(res,parent,res.size()-1);
}
}
/*
*堆排序首先将输入的数组建成一个最大堆。
*因为数组中最大值总是在res[0],故通过将其与res[res.size()-1]交换,
*便可将该元素放到正确的位置。在剩余节点中,原来根的孩子节点仍然是一个
*最大堆,然而新的根节点可能会违背最大堆的性质。为了维护最大堆的性质,调用max_heap
*从而将剩下的堆构造成一个最大堆。一直循环直到从n-1降到1.
*
*@author qls
*@2018/8/2 下午17:13
**/
void Sort::Heapsort(vector<int>& res)
{
build_heap(res);
for (int i = res.size() - 1;i > 0;--i) {
swap(res[0],res[i]); //交换两个值
max_heap(res,0,i-1); //重新构造堆
}
}