这篇文章把常用的七个排序算法都实现了一遍,同时分析了各个算法的特点。
排序分类:
内部排序和外部排序:
- 若整个排序过程不需要访问外存便能完成,则称此类排序问题为内部排序。反之,若参加排序的记录数量很大,整个序列的排序过程不可能在内存中完成,则称此类排序问题为外部排序。
- 在内部排序中,根据排序过程中所依据的原则可以将它们分为5类:插入排序、交换排序、选择排序、归并排序和基数排序;
稳定排序和不稳定排序:
- 假设在待排序的文件中,存在两个或两个以上的记录具有相同的关键字,在用某种排序法排序后,若这些相同关键字的元素的相对次序仍然不变,则这种排序方法是稳定的。
- 冒泡,插入,基数,归并 属于稳定排序
- 选择,快速,希尔,堆 属于不稳定排序。
就地排序:
- 若排序算法所需的辅助空间并不依赖于问题的规模n,即辅助空间为O(1),则称为就地排序。
归并排序和堆排序、快速排序的比较
若从空间复杂度来考虑:首选堆排序,其次是快速排序,最后是归并排序。
若从稳定性来考虑,应选取归并排序,因为堆排序和快速排序都是不稳定的。
若从平均情况下的排序速度考虑,应该选择快速排序。
#include <iostream>
#include <vector>
#include <ctime>
#include <queue>
using namespace std;
/* Heap Sort */
void heap_sort(vector<double>& a) {
priority_queue<double, vector<double>, greater<double> > nums_heap;
for(auto& r : a)
nums_heap.push(r);
int i = 0;
while(!nums_heap.empty()) {
a[i++] = nums_heap.top();
nums_heap.pop();
}
}
/* Merge Sort */
void merge_array(vector<double>& a, long first, long mid, long last) {
vector<double> temp_array;
int i = first, u = mid; // first array
int j = mid + 1, v = last; // second array
int k = 0;
while(i <= u && j <= v) {
if(a[i] < a[j])
temp_array.push_back(a[i++]);
else
temp_array.push_back(a[j++]);
}
while(i <= u)
temp_array.push_back(a[i++]);
while(j <= v)
temp_array.push_back(a[j++]);
for(int i = 0; i < temp_array.size(); i++) {
a[first + i] = temp_array[i];
}
}
void merge_sort(vector<double>& a, int first, int last) {
if(first < last) {
int mid = (first + last) / 2;
merge_sort(a, first, mid);
merge_sort(a, mid + 1, last);
merge_array(a, first, mid, last);
}
}
/* Quick Sort */
void quick_sort(vector<double>& nums, long left, long right) {
if(left < right) {
swap(nums[left], nums[(left + right)/2]);
int i = left, j = right, x = nums[left];
while(i < j) {
while(i < j && nums[j] >= x)
--j;
if(i < j)
nums[i++] = nums[j];
while(i < j && nums[i] < x)
++i;
if(i < j)
nums[j--] = nums[i];
}
nums[i] = x;
quick_sort(nums, left, i - 1);
quick_sort(nums, i + 1, right);
}
}
/* Choose Sort */
void choose_sort(vector<double>& nums) {
long flag_position = 0;
for(int i = 0; i < nums.size(); ++i) {
flag_position = i;
for(int j = i + 1; j < nums.size(); ++j) {
if(nums[j] < nums[flag_position])
flag_position = j;
}
swap(nums[i], nums[flag_position]);
}
}
/* Shell Sort */
void shell_sort(vector<double>& nums) {
for(int gap = nums.size()/2; gap > 0; gap /= 2) {
for(int i = 1; i < nums.size(); ++i)
for(int j = i - 1; j > 0 && nums[j] > nums[j + 1]; --j)
swap(nums[j], nums[j + 1]);
}
}
/* Insert Sort */
void insert_sort(vector<double>& nums) {
for (int i = 1; i < nums.size(); i++)
for (int j = i - 1; j > 0 && nums[j] > nums[j + 1]; --j) {
swap(nums[j], nums[j + 1]);
}
}
/* Bubble Sort */
void bubble_sort(vector<double>& nums) {
int flag = nums.size();
while (flag > 0) {
int k = flag;
flag = 0;
for (int i = 1; i < k; ++i)
{
if (nums[i - 1] > nums[i]) {
swap(nums[i - 1], nums[i]);
flag = i;
}
}
}
}
/* print sorted number */
void print(vector<double>& nums) {
for (int i = 0; i < nums.size(); ++i)
{
cout << nums[i] << endl;
}
}
/* generate random number */
double random(double start, double end)
{
return start + (end - start)*rand() / (RAND_MAX + 1.0);
}
int main(int argc, char const *argv[])
{
int sort_nums_size = 100000;
// random number
srand(unsigned(time(0)));
rand();
vector<double> nums;
for (long i = 0; i < sort_nums_size; i++) {
nums.push_back(random(0, 10000));
}
// sort, a example of heap sort
clock_t start_time = clock();
heap_sort(nums);
clock_t time_cost = clock() - start_time;
cout << "Heap Sort: " << time_cost << "ms" << endl; // time cost
// print(nums); // print elements
system("pause");
return 0;
}