您的位置:首页 > 编程语言 > C语言/C++

九大经典排序算法整理及其源代码分享(纯C++版)

2017-09-03 20:48 405 查看
九大经典排序算法整理及其源代码分享(纯C++版)

[TOC]

头文件–9sortEx.h

#ifndef SORTEX_H_
#define SORTEX_H_

typedef int Comparable;

#include <vector>
using std::vector;

class sortEx
{
public:
//static bool lessThan(Comparable v, Comparable w);
void exch(int i, int j);
bool isSorted()const;
void show()const;
virtual void sort() = 0;
protected:
sortEx(int n = 0);
vector<Comparable> a;
};

class insertSortStraight :public sortEx
{
public:
insertSortStraight(int n):sortEx(n){ }
void sort();
};

class insertSortShell :public sortEx
{
public:
insertSortShell(int n) :sortEx(n)
{
}
void sort();
};

class swapSortBubble :public sortEx
{
public:
swapSortBubble(int n) :sortEx(n)
{
}
void sort();
};

class swapSortQuick :public sortEx
{
public:
swapSortQuick(int n) :sortEx(n)
{
}
void sort();
private:
int Partition(int st, int ed);   //[st, ed]
void sort(int st, int ed);       //[st, ed)
};

class selectionSortSimple :public sortEx
{
public:
selectionSortSimple(int n) :sortEx(n)
{
}
void sort();
};

class selectionSortHeap :public sortEx
{
public:
selectionSortHeap(int n) :sortEx(n)
{
}
void sort();
private:
void createHeap();
void heapAdjust(int totalN, int pos);
};

class mergeSort :public sortEx
{
public:
mergeSort(int n) :sortEx(n)
{
aux.resize(n);
}
//自顶向下的归并
void sort();
//自底向上的归并
void sortAnther();
private:
void sort(int st, int ed);            //[st, ed]
void merge(int st, int mid, int ed);  //[st, ed]
vector<Comparable> aux;
int minNum(int a, int b)
{
return a < b ? a : b;
}
};

class countSort :public sortEx
{
public:
countSort(int n) :sortEx(n)
{
}
void sort();
};

class radixSort :public sortEx
{
public:
radixSort(int n) :sortEx(n), RADIX(10)
{
}
void sort();
private:
int getRadix(int num, int sq);
void Distribute(int sq, vector<int>& cnt);
void Collect(int sq, vector<int>& cnt, vector<int>& tmp);
const int RADIX;
};

#endif


类实现文件–9sortEx.cpp

/*
* ---------------------------------------------------
*  Copyright (c) 2017 josan All rights reserved.
* ---------------------------------------------------
*
*               创建者: Josan
*             创建时间: 2017/9/3 15:28:42
*/
#include <iostream>
#include <vector>
#include <cassert>
#include <iomanip>
#include <cmath>
#include <queue>
#include <functional>
#include <cassert>
#include "9sortEx.h"
using namespace std;

sortEx::sortEx(int n /* = 0 */)
{
assert(0 <= n);
a.resize(n);
for(int i = 0; i < n; ++i)
{
cin >> a[i];
}
}

void sortEx::exch(int i, int j)
{
Comparable tmp;
tmp = a[i];
a[i] = a[j];
}

bool sortEx::isSorted()const
{
int<
4000
/span> n = static_cast<int>(a.size());
for(int i = 1; i < n; ++i)
{
if(a[i - 1] > a[i])
{
return false;
}
}
return true;
}

void sortEx::show()const
{
assert(isSorted());
int n = static_cast<int>(a.size());
int sz = 0;
for(int i = 0; i < n; ++i)
{
cout << left << setw(4) << a[i];
sz = (sz + 1) % 10;
if(0 == sz)
{
cout << endl;
}
}
cout << endl;
}

void insertSortStraight::sort()
{
int n = static_cast<int>(a.size());
for(int i = 1; i < n; ++i)
{
Comparable tem = a[i];
int j = i;
for(; 1 <= j&&tem < a[j - 1]; --j)
{
a[j] = a[j - 1];
}
a[j] = tem;
}
}

void insertSortShell::sort()
{
int n = static_cast<int>(a.size());
for(int step = (n >> 1); 1 <= step; step >>= 1)
{
for(int st = 0; st < step; ++st)
{
for(int i = st + step; i < n; i += step)
{
Comparable tem = a[i];
int j = i;
for(; st + step <= j&&tem < a[j - step]; j -= step)
{
a[j] = a[j - step];
}
a[j] = tem;
}
}
}
}

void swapSortBubble::sort()
{
int n = static_cast<int>(a.size());
for(int i = 1; i < n; ++i)
{
for(int j = 0; j < n - i; ++j)
{
if(a[j + 1] < a[j])
{
exch(j, j+1);
}
}
}
}

void swapSortQuick::sort()
{
int n = static_cast<int>(a.size());
sort(0, n);
}

void swapSortQuick::sort(int st, int ed)
{
if(ed - st < 2)
{
return;
}
int pos = Partition(st, ed - 1);
sort(st, pos);
sort(pos + 1, ed);
}

int swapSortQuick::Partition(int st, int ed)
{
Comparable tem = a[st];
while(st < ed)
{
while(st < ed&&tem <= a[ed])
{
--ed;
}
a[st] = a[ed];
while(st < ed&&a[st] <= tem)
{
++st;
}
a[ed] = a[st];
}
a[st] = tem;
return st;
}

void selectionSortSimple::sort()
{
int n = static_cast<int>(a.size());
for(int i = 0; i < n - 1; ++i)
{
int minIdx = i;
for(int j = i + 1; j < n; ++j)
{
if(a[j] < a[minIdx])
{
minIdx = j;
}
}
if(minIdx != i)
{
exch(i, minIdx);
}
}
}

//使用标准库的优先队列,进行堆排序
void selectionSortHeap::sort()
{
int n = static_cast<int>(a.size());
priority_queue<int, vector<int>, greater<int>> Q;   //小顶堆
//默认是大顶堆
// priority_queue<int, vector<int>, less<int>> Q;    //使用priority_queue<int> Q;一样
for(auto x : a)
{
Q.push(x);
}
int i = 0;
while(!Q.empty())
{
a[i++] = Q.top();
Q.pop();
}
}

//void selectionSortHeap::sort()
//{
//  int n = static_cast<int>(a.size());
//  createHeap();
//  for(int i = n - 1; 0 < i; --i)
//  {
//      exch(i, 0);
//      heapAdjust(i, 0);
//  }
//}
//
//void selectionSortHeap::createHeap()
//{
//  int n = static_cast<int>(a.size());
//  for(int i = (n - 1) / 2; 0 <= i; --i)
//  {
//      heapAdjust(n, i);
//  }
//}
//
//void selectionSortHeap::heapAdjust(int totalN, int pos)
//{
//  int n = static_cast<int>(a.size());
//  Comparable tem = a[pos];
//  int i = pos;
//  for(int j = pos * 2 + 1; j < n; j = j * 2 + 1)
//  {
//      if(j + 1 < n&&a[j] < a[j + 1])
//      {
//          ++j;
//      }
//      if(tem >= a[j])
//      {
//          break;
//      }
//      else
//      {
//          a[i] = a[j];
//          i = j;
//      }
//  }
//  a[i] = tem;
//}

void mergeSort::sort()
{
int n = static_cast<int>(a.size());
sort(0, n - 1);
}

void mergeSort::sort(int st, int ed)
{
if(st < ed)
{
int mid = st + (ed - st) / 2;
sort(st, mid);
sort(mid + 1, ed);
merge(st, mid, ed);
}
}

void mergeSort::merge(int st, int mid, int ed)
{
int i = st;
int j = mid + 1;
for(int k = st; k <= ed; ++k)
{
aux[k] = a[k];
}

for(int k = st; k <= ed; ++k)
{
if(i > mid)
{
a[k] = aux[j++];
}
else if(j > ed)
{
a[k] = aux[i++];
}
else if(aux[j] < aux[i])
{
a[k] = aux[j++];
}
else
{
a[k] = aux[i++];
}
}
}

void mergeSort::sortAnther()
{
int n = static_cast<int>(a.size());
for(int sz = 1; sz < n; sz <<= 1)
{
for(int st = 0; st < n - sz; st += sz * 2)
{
merge(st, st + sz + 1, minNum(st + sz + sz - 1, n - 1));
}
}
}
void countSort::sort()
{
//假设数组元素在0~499之间
vector<int> cntAux(500, 0);
int n = static_cast<int>(a.size());
for(int i = 0; i < n; ++i)
{
++cntAux[a[i]];
}
for(int i = 1; i < 500; ++i)
{
cntAux[i] += cntAux[i - 1];
}

vector<Comparable> tmp(a);
for(int i = n - 1; 0 <= i; --i)
{
a[--cntAux[tmp[i]]] = tmp[i];
}
}

void radixSort::sort()
{
int n = static_cast<int>(a.size());
int d = 3;
vector<int> cnt(RADIX);
vector<Comparable> tmp(n);

for(int i = 0; i < d; ++i)
{
//分配
Distribute(i, cnt);
//收集
Collect(i, cnt, tmp);
}
}

int radixSort::getRadix(int num, int sq)
{
return (num / static_cast<int>(pow(RADIX, sq))) % RADIX;
}

void radixSort::Distribute(int sq, vector<int>& cnt)
{
//初始化
int n = static_cast<int>(a.size());
for(auto& x : cnt)
{
x = 0;
}
for(int i = 0; i < n; ++i)
{
int ord = getRadix(a[i], sq);
++cnt[ord];
}
}

void radixSort::Collect(int sq, vector<int>& cnt, vector<int>& tmp)
{
int n = static_cast<int>(a.size());
for(int i = 1; i < RADIX; ++i)
{
cnt[i] += cnt[i - 1];
}
for(int
dfe3
i = 0; i < n; ++i)
{
tmp[i] = a[i];
}
for(int i = n - 1; 0 <= i; --i)
{
int ord = getRadix(tmp[i], sq);
a[--cnt[ord]] = tmp[i];
}
}


测试程序–test.cpp

/*
* ---------------------------------------------------
*  Copyright (c) 2017 josan All rights reserved.
* ---------------------------------------------------
*
*               创建者: Josan
*             创建时间: 2017/9/3 16:50:31
*/
#include <iostream>
#include <vector>
#include <string>
#include <cstdlib>
#include <fstream>
#include <ctime>
#include "9sortEx.h"
using namespace std;

#define INPUTTEST 0
#define OUTPUTTEST 0
template <typename T>
static void testSort(const string& sortName)
{
ifstream fin("tinyUnsortedNum.txt");
//cinbk作为cin对象的读取缓冲区的临时存储对象
streambuf* cinbk;
//[old]streambuf* rdbuf(streambuf* newbf);
//调用这个方法可以设置新的读取缓冲区,返回旧的缓冲区
cinbk = cin.rdbuf(fin.rdbuf());
string str(sortName);
str += "tinySortedNum.txt";
ofstream fout(str);
//coutbk作为cout对象的写入缓冲区的临时存储对象
streambuf* coutbk;
coutbk = cout.rdbuf(fout.rdbuf());
//--------------- start of test --------------
clock_t t_st, t_ed;
t_st = clock();
int n;
cin >> n;
T sTiny(n);
sTiny.sort();
sTiny.show();
t_ed = clock();
cout << "The time of sort is " << t_ed - t_st << " ms." << endl;

fin.close();
fin.open("mediumUnsortedNum.txt");
fout.close();
str = sortName;
str += "mediumSortedNum.txt";
fout.open(str);
t_st = clock();
cin >> n;
T sMedium(n);
sMedium.sort();
sMedium.show();
t_ed = clock();
cout << "The time of sort is " << t_ed - t_st << " ms." << endl;

fin.close();
fin.open("largeUnsortedNum.txt");
fout.close();
str = sortName;
str += "largeSortedNum.txt";
fout.open(str);
t_st = clock();
cin >> n;
T sLarge(n);
sLarge.sort();
sLarge.show();
t_ed = clock();
cout << "The time of sort is " << t_ed - t_st << " ms." << endl;
//--------------- end   of test --------------
fout.close();
cout.rdbuf(coutbk);
fin.close();
cin.rdbuf(cinbk);
}

static void test()
{
testSort<insertSortStraight>("insertSortStraight");
testSort<insertSortShell>("insertSortShell");
testSort<swapSortBubble>("swapSortBubble");
testSort<swapSortQuick>("swapSortQuick");
testSort<selectionSortSimple>("selectionSortSimple");
testSort<selectionSortHeap>("selectionSortHeap");
testSort<mergeSort>("mergeSort");
testSort<countSort>("countSort");
testSort<radixSort>("radixSort");
}

int main(int argc, char* argv[])
{
#if INPUTTEST
ifstream fin("tinyUnsortedNum.txt");
//cinbk作为cin对象的读取缓冲区的临时存储对象
streambuf* cinbk;
//[old]streambuf* rdbuf(streambuf* newbf);
//调用这个方法可以设置新的读取缓冲区,返回旧的缓冲区
cinbk = cin.rdbuf(fin.rdbuf());
#endif
#if OUTPUTTEST
ofstream fout("out.txt");
//coutbk作为cout对象的写入缓冲区的临时存储对象
streambuf* coutbk;
coutbk = cout.rdbuf(fout.rdbuf());
#endif
//--------------- start of main --------------
test();
//--------------- end   of main --------------
#if OUTPUTTEST
fout.close();
cout.rdbuf(coutbk);
#endif
#if INPUTTEST
fin.close();
cin.rdbuf(cinbk);
#endif
return 0;
}


测试文件和测试环境说明

测试文件

所有的测试文件都是随机产生。其中,数值的范围在[0, 500)之间。

tinyUnsortedNum.txt
数据规模为10

mediumUnsortedNum.txt
数据规模为200

largeUnsortedNum.txt
数据规模为10000

测试环境

IDE环境: Visual Studio 2015 Enterprise (Debug模式下)

处理器: AMD A8-7650K Radeon R7, 10 Compute Cores 4C+6G 3.30GHz

测试结果

直接插入排序:
The time of sort is 0 ms.
The time of sort is 17 ms.
The time of sort is 38240 ms.

希尔排序:
The time of sort is 0 ms.
The time of sort is 5 ms.
The time of sort is 426 ms.

冒泡排序:
The time of sort is 0 ms.
The time of sort is 23 ms.
The time of sort is 51979 ms.

快速排序:
The time of sort is 1 ms.
The time of sort is 3 ms.
The time of sort is 271 ms.

简单选择排序:
The time of sort is 0 ms.
The time of sort is 21 ms.
The time of sort is 51855 ms.

堆排序:
The time of sort is 1 ms.
The time of sort is 7 ms.
The time of sort is 4450 ms.

归并排序:
The time of sort is 0 ms.
The time of sort is 7 ms.
The time of sort is 490 ms.

计数排序:
The time of sort is 1 ms.
The time of sort is 2 ms.
The time of sort is 108 ms.

基数排序:
The time of sort is 1 ms.
The time of sort is 4 ms.
The time of sort is 212 ms.


结果分析

都说快速排序是
O(nlgn)
中最好的,直接插入排序是
O(n^2)
中最好的。现在可以直接看到实验结果确实是这样的。(多次随机后,仍然得出此结论。)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  c++ 数据结构