排序算法作为基础的算法,虽然如今没有多少人会自己手动去实现,但作为基础的算法,最近温故了一下,并写了一个简单的测试比较框架,可以给新学习的小伙伴使用同时也自己mark下,以备以后有用。
#include <iostream>
#include <algorithm>
#include <string>
#include <map>
#include <time.h>
using namespace std;
int myRand() {
return (rand() % 100);
}
template <class OType, int count>
void prinsourceArray(const OType (&a)[count]){
copy(a, a + count, ostream_iterator<OType>(cout, "\t"));
}
template <int count>
void randomArray(int (&arr)[count]) {
random_shuffle(arr, arr + count);
}
template <int count>
void copy(int (&source)[count], int (&direction)[count]) {
copy(source, source + count, direction);
}
#define PRINT_SORT(fun, source, param) do {\
cout << #fun << " : " << endl;\
copy(source, param);\
clock_t startTime = clock();\
int runTimes = 1000000;\
for (int i = 0; i < runTimes; ++i) {\
fun(param);\
}\
clock_t endTime = clock();\
prinsourceArray(param);\
double runTime = (double)(endTime - startTime) / CLOCKS_PER_SEC / runTimes;\
cout << #fun << " run time : " << runTime << "s"<< endl << endl;\
resultSet.insert(pair< double, string >(runTime, #fun));\
} while(0)
// 因为采用数组存储,故需要进行挪位,之前实现的时候,直接交换位置,其实这样也就相当于冒泡排序了
//template <int count>
//void insertSort(int (&arr)[count]) {
// for (int i = 1; i < count; ++i) {
// for (int j = i; arr[j] < arr[j - 1] && j > 0;) {
// swap(arr[j], arr[j - 1]);
// --j;
// }
// }
//}
/********************************************
插入排序:每次追加元素,都直接将元素插入到其正确的位置,再调整整个序列。
********************************************/
template <int count>
void insertSort(int (&arr)[count]) {
for (int i = 1; i < count; ++i) {
int j = i;
if (arr[i] < arr[i - 1]) {
j = i - 1;
while (j >= 0 && arr[i] < arr[j]) {
--j;
}
++j;
}
if (i != j) {
int tmpVal = arr[i];
copy(arr + j, arr + i, arr + j + 1);
arr[j] = tmpVal;
}
}
}
//template <int count>
//void shellSort(int (&arr)[count]) {
// for (int direction = count / 2; direction >= 1; direction /= 2) {
// for (int m = 0; m < direction; ++m) {
// for (int i = direction + m; i < count; i += direction) {
// for (int j = i; arr[j] < arr[j - direction] && j >=direction;) {
// swap(arr[j], arr[j - direction]);
// j -= direction;
// }
//
// }
// }
// }
//}
/********************************************
希尔排序:多次的插入排序,每次所见插入排序的采样间隔,最后进行一次插入排序。
********************************************/
template <int count>
void shellSort(int (&arr)[count]) {
for (int direction = count / 2; direction >= 1; direction /= 2) {
for (int m = 0; m < direction; ++m) {
for (int i = direction + m; i < count; i += direction) {
int j = i;
if (arr[i] < arr[i - direction]) {
j = i - direction;
while(j >= 0 && arr[i] < arr[j]) {
j -= direction;
}
j += direction;
}
if (i != j) {
int tmpVal = arr[i];
for (int t = i; t > j; t -= direction) {
arr[t] = arr[t - direction];
}
arr[j] = tmpVal;
}
}
}
}
}
/********************************************
选择排序:每次选择一个最大的元素,追加到有序数列末端(最初为空序列,即加入序列即可);升级版本的选择排序:一次寻找最大和最小的元素。
********************************************/
template <int count>
void selectSort(int (&arr)[count]) {
for (int i = 0; i < count; ++i) {
int minValID = i;
for (int j = i; j < count; ++j) {
if (arr[minValID] > arr[j]) {
minValID = j;
}
}
if (minValID != i) {
swap(arr[minValID], arr[i]);
}
}
}
template <int count>
void updatedSelectSort(int (&arr)[count]) {
for (int i = 0; i < count - i; ++i) {
int minValID = i;
int maxValID = i;
for (int j = i; j < count - i; ++j) {
if (arr[maxValID] < arr[j]) {
maxValID = j;
}
if (arr[minValID] > arr[j]) {
minValID = j;
}
}
if (minValID != i) {
swap(arr[minValID], arr[i]);
if (maxValID == i) {
maxValID = minValID;
}
}
if (maxValID != count - i - 1) {
swap(arr[maxValID], arr[count - i - 1]);
}
}
}
template <class RandomAccessIterator, class Compare>
struct StlFunWraper {
typedef void (* SortFun)(RandomAccessIterator first, RandomAccessIterator last, Compare comp);
StlFunWraper(SortFun fun) : m_fun(fun) {}
template <int count>
void operator()(int (&arr)[count]) {
m_fun(arr, arr + count, Compare());
}
SortFun m_fun;
};
map< double, string > resultSet;
template <class k, class T>
void printMap(const pair<k, T> &val) {
cout << val.first << "\t" << val.second << endl;
}
const int ACount = 10;
int main()
{
srand(time(0));
int sourceArray[ACount];
int sortArray[ACount];
generate(sourceArray, sourceArray + ACount, myRand);
cout << "sourceArray : " << endl;
prinsourceArray(sourceArray);
cout << endl;
// 框架中,只需要此处添加算法,即可运行并按照运行时间排序
// 这里使用两个数组,主要考虑到每次排序环境一样,才能对算法运行时间进行排序。
PRINT_SORT(insertSort, sourceArray, sortArray);
PRINT_SORT(shellSort, sourceArray, sortArray);
PRINT_SORT(selectSort, sourceArray, sortArray);
PRINT_SORT(updatedSelectSort, sourceArray, sortArray);
//stl sort
PRINT_SORT((StlFunWraper< int[], less<int> >(&sort)), sourceArray, sortArray);
cout << "*******************reslut summary******************" << endl;
for_each(resultSet.begin(), resultSet.end(), printMap<double, string>); // 将运行结果增序打出以统计算法的运行事件
return 0;
}
可以看到,其中很多运用到了stl库中的内容,但均起辅助作用,为了框架实现更加方便。
以下附上运行结果:
sourceArray :
13 61 64 40 90 97 65 33 9 4
insertSort :
4 9 13 33 40 61 64 65 90 97
insertSort run time : 3.1e-008s
shellSort :
4 9 13 33 40 61 64 65 90 97
shellSort run time : 9.3e-008s
selectSort :
4 9 13 33 40 61 64 65 90 97
selectSort run time : 1.25e-007s
updatedSelectSort :
4 9 13 33 40 61 64 65 90 97
updatedSelectSort run time : 1.25e-007s
(StlFunWraper< int[], less<int> >(&sort)) :
4 9 13 33 40 61 64 65 90 97
(StlFunWraper< int[], less<int> >(&sort)) run time : 1.09e-007s
*******************reslut summary******************
3.1e-008 insertSort
9.3e-008 shellSort
1.09e-007 (StlFunWraper< int[], less<int> >(&sort))
1.25e-007 selectSort
代码中已经附上注释,至于其他几种排序算法,将在后面进一步添加。