分別寫了選擇、冒泡、插入、堆、歸併、快排的實現,以及基於快排的內省排序,並於STL的排序相比較。
//algo.h
#pragma once
int min(int x, int y)
{
return x < y ? x : y;
}
int max(int x, int y)
{
return x > y ? x : y;
}
void swap(int& x, int& y)
{
int temp = x;
x = y;
y = temp;
}
//sort.h
#pragma once
#include<vector>
#include"algo.h"
void insertsort(std::vector<int> &vec)
{
int m = vec.size();
for (int i = 1; i < m; i++)
{
int temp = vec[i];
int j = i - 1;
while (j >= 0 && temp < vec[j])
{
vec[j + 1] = vec[j];
j--;
}
vec[j+1] = temp;
}
}
void maopao(std::vector<int> &vec)
{
int m = vec.size();
for (int i = 0; i < m; i++)
{
for (int j = 0; j < m - i - 1; j++)
{
if (vec[j] > vec[j + 1])
swap(vec[j], vec[j + 1]);
}
}
}
void xuanze(std::vector<int> &vec)
{
int m = vec.size();
for (int i = 0; i < m; i++)
{
int index = i;
for (int j = i; j < m; j++)
{
if (vec[j] < vec[index])
{
index = j;
}
}
swap(vec[i], vec[index]);
}
}
//heapsort.h
#pragma once
#include<vector>
#include"algo.h"
void up(std::vector<int>& vec, int i)
{
int par = (i - 1) / 2;
while (par && vec[i]<vec[par])
{
swap(vec[i], vec[par]);
i = par;
par = (i - 1) / 2;
}
}
void down(std::vector<int> &vec, int i, int end)
{
int child = i * 2 + 1;
while (child < end)
{
if (child + 1 < end && vec[child] < vec[child + 1])
child++;
if (vec[i] < vec[child])
swap(vec[i], vec[child]);
else
break;
i = child;
child = i * 2 + 1;
}
}
void heapsort(std::vector<int>& vec)
{
int m = vec.size();
for (int i = m/2-1; i>=0; i--)
{
down(vec, i, m);
}
for (int i = m-1; i>0; i--)
{
swap(vec[0], vec[i]);
down(vec, 0, i);
}
}
//mergesort.h
#pragma once
#include<vector>
#include"algo.h"
void merge(std::vector<int> &vec, int left_beg, int right_beg, int right_end, std::vector<int> &fuzhu)
{
int left_end = right_beg - 1;
int i = left_beg, j = right_beg;
int index = left_beg;
while (i <= left_end && j <= right_end)
{
if (vec[i] < vec[j])
fuzhu[index++] = vec[i++];
else
fuzhu[index++] = vec[j++];
}
while (i <= left_end)
fuzhu[index++] = vec[i++];
while (j <= right_end)
fuzhu[index++] = vec[j++];
for (int beg = left_beg; beg <= right_end; beg++)
vec[beg] = fuzhu[beg];
}
void mergesort_recusive(std::vector<int> &vec, int beg, int end, std::vector<int> &fuzhu)
{
if (beg < end)
{
int mid = beg + (end - beg) / 2;
mergesort_recusive(vec, beg, mid, fuzhu);
mergesort_recusive(vec, mid + 1, end, fuzhu);
merge(vec, beg, mid+1, end, fuzhu);
}
}
void mergesort(std::vector<int> &vec)
{
int m = vec.size();
std::vector<int> fuzhu(m, 0);
mergesort_recusive(vec, 0, m - 1, fuzhu);
}
//qsort.h
#pragma once
#include<vector>
#include"algo.h"
void mid_of_three_swap(std::vector<int>& vec, int beg, int end)//頭中尾三個取中間值與尾元素交換
{
int mid = beg + (end - beg) / 2;
int mid_index;
if (vec[beg] > vec[mid])
{
if (vec[mid] > vec[end])
{
swap(vec[mid], vec[end]);
return;
}
else
{
if (vec[beg] < vec[end]) swap(vec[beg], vec[end]);
return;
}
}
else
{
if (vec[beg] > vec[end])
{
swap(vec[beg], vec[end]);
return;
}
else
{
if (vec[mid] < vec[end]) swap(vec[mid], vec[end]);
return;
}
}
}
int partition_Lomuto(std::vector<int> &vec, int beg, int end)//單向,加上一點優化
{
int key = vec[end];
while (vec[beg] < key)//可以避免已經排好的情況
{
if (++beg == end) return beg;
}
int next = beg + 1;
for (; next < end; next++)
{
if (vec[next] < key)
{
swap(vec[next], vec[beg++]);
}
}
swap(vec[beg], vec[end]);
return beg;
}
int partition_Lomuto2(std::vector<int> &vec, int beg, int end)//單向,無優化
{
int key = vec[end];
for (int next = beg; next < end; next++)
{
if (vec[next] < key)
{
swap(vec[next], vec[beg++]);
}
}
swap(vec[beg], vec[end]);
return beg;
}
int partition_Hoare(std::vector<int> &vec, int beg, int end)//雙向
{
int key = vec[end];
while (beg<end)
{
while (beg < end && vec[beg] <= key) beg++;
vec[end] = vec[beg];
while (beg<end && vec[end] >= key) end--;
vec[beg] = vec[end];
}
vec[end] = key;
return end;
}
void qsort_recusive(std::vector<int> &vec, int beg, int end)
{
if (beg < end)
{
mid_of_three_swap(vec, beg, end);
int index = partition_Hoare(vec, beg, end);
qsort_recusive(vec, beg, index - 1);
qsort_recusive(vec, index + 1, end);
}
}
void qsort(std::vector<int> &vec)
{
qsort_recusive(vec, 0, vec.size() - 1);
}
//mysort.h
#pragma once
#include<vector>
#include"algo.h"
void _mid_of_three_swap(std::vector<int>& vec, int beg, int end)
{
int mid = beg + (end - beg) / 2;
int mid_index;
if (vec[beg] > vec[mid])
{
if (vec[mid] > vec[end])
{
swap(vec[mid], vec[end]);
return;
}
else
{
if (vec[beg] < vec[end]) swap(vec[beg], vec[end]);
return;
}
}
else
{
if (vec[beg] > vec[end])
{
swap(vec[beg], vec[end]);
return;
}
else
{
if (vec[mid] < vec[end]) swap(vec[mid], vec[end]);
return;
}
}
}
int _lg(int n)
{
int ret = 0;
while (n>1)
{
ret++;
n = n >> 1;
}
return ret;
}
int _partition_Hoare(std::vector<int> &vec, int beg, int end)
{
int key = vec[end];
while (beg<end)
{
while (beg < end && vec[beg] <= key) beg++;
vec[end] = vec[beg];
while (beg<end && vec[end] >= key) end--;
vec[beg] = vec[end];
}
vec[end] = key;
return end;
}
void _insert(std::vector<int> &vec, int beg, int end)
{
for (int i = beg+1; i <= end; i++)
{
int temp = vec[i];
int j = i - 1;
while (j >= beg && temp < vec[j])
{
vec[j + 1] = vec[j];
j--;
}
vec[j + 1] = temp;
}
}
void _down(std::vector<int> &vec, int i, int end)
{
int child = i * 2 + 1;
while (child < end)
{
if (child + 1 < end && vec[child] < vec[child + 1])
child++;
if (vec[i] < vec[child])
swap(vec[i], vec[child]);
else
break;
i = child;
child = i * 2 + 1;
}
}
void _heapsort(std::vector<int>& vec, int beg, int end)
{
int m = end-beg+1;
for (int i = beg + m / 2 - 1; i >= beg; i--)
{
_down(vec, i, m);
}
for (int i = beg + m - 1; i>beg; i--)
{
swap(vec[beg], vec[i]);
_down(vec, beg, i);
}
}
void _qsort_recusive(std::vector<int> &vec, int beg, int end, int depth_limit)
{
if (--depth_limit == 0)
{
_heapsort(vec, beg, end);
return;
}
if (end-beg>16)
{
_mid_of_three_swap(vec, beg, end);
int index = _partition_Hoare(vec, beg, end);
_qsort_recusive(vec, beg, index - 1, depth_limit);
_qsort_recusive(vec, index + 1, end, depth_limit);
}
else
{
_insert(vec, beg, end);
}
}
void mysort(std::vector<int> &vec)
{
int m = vec.size();
_qsort_recusive(vec, 0, m - 1, 2*_lg(m));
}
//main.h
#include<vector>
#include<iostream>
#include<ctime>
#include<algorithm>
#include"qsort.h"
#include"heapsort.h"
#include"sort.h"
#include"mergesort.h"
#include"mysort.h"
using namespace std;
void show(vector<int> &vec)
{
for (auto x : vec)
{
cout << x << " ";
}
cout << endl;
}
void test()
{
srand(time(0));
vector<int> vec(10000000, 0);
for (int i = 0; i < 10000000; i++)
{
vec[i] += rand() % 10000000;
}
vector<int> vec0(vec);
vector<int> vec1(vec);
vector<int> vec2(vec);
vector<int> vec3(vec);
vector<int> vec4(vec);
vector<int> vec5(vec);
vector<int> vec6(vec);
cout << "數據量 " << vec.size() << endl;
clock_t a, b;
a = clock();
sort(vec.begin(), vec.end());
b = clock();
cout << "stl " << b - a << endl;
a = clock();
mysort(vec0);
b = clock();
cout << "我的 " << b - a << endl;
//show(vec0);
a = clock();
qsort(vec1);
b = clock();
cout << "快排 " << b - a << endl;
a = clock();
mergesort(vec2);
b = clock();
cout << "歸併 " << b - a << endl;
a = clock();
heapsort(vec3);
b = clock();
cout << "堆 " << b - a << endl;
a = clock();
xuanze(vec4);
b = clock();
cout << "選擇 " << b - a << endl;
a = clock();
maopao(vec5);
b = clock();
cout << "冒泡 " << b - a << endl;
a = clock();
insertsort(vec6);
b = clock();
cout << "插入 " << b - a << endl;
}
void main()
{
test();
char c; cin >> c;
}
單位:ms
內省快排,一方面限制了遞歸的深度適時採取堆排序,另一方面當範圍元素個數少時(16以下)採用插入排序。
只是在快排上做了一些微小的工作,性能上相較快排提升了不少,與stl裏的sort性能也接近了不少。
stl的sort分析見:http://www.udpwork.com/item/12284.html