排序算法小结
1.冒泡排序 BubbleSort
冒泡排序是一种简单的排序算法,它重复遍历待排序列,并以正确的顺序交换相邻元素的位置。当所有的交换完成后,该待排序列完成排序。
实现如下:
void my_sort::MySort::BubbleSort0(std::vector<int> &i_arr)
{
size_t i_arr_len = i_arr.size();
for (size_t i = 0; i < i_arr_len; i++)
{
for (size_t j = 0; j < i_arr_len; j++)
{
if (i_arr[i] < i_arr[j])
{
my_sort::my_swap(i_arr[i], i_arr[j]);
}
}
}
}
void my_sort::MySort::BubbleSort(std::vector<int> &i_arr)
{
size_t i_arr_len = i_arr.size();
for (int i = 0; i < i_arr_len; i++)
{
for (int j = i_arr_len - 2; j >= i; j--)
{
if (i_arr[j] > i_arr[j + 1])
my_sort::my_swap(i_arr[j], i_arr[j + 1]);
}
}
}
注:后者是冒泡排序的一种常用做法。
2.选择排序 Selection Sort
选择排序是一种直观的排序算法,其原理是每次选出待排序列中的最小值放于恰当的位置,所有交换完成后即完成排序工作。
实现如下:
void my_sort::MySort::SelectSort(std::vector<int>& i_arr)
{
size_t i_arr_len = i_arr.size();
for (int i = 0; i < i_arr_len; i++)
{
int min = i;
for (int j = i + 1; j < i_arr_len; j++)
{
if (i_arr[j] < i_arr[min])
min = j;
}
if (i != min)
my_sort::my_swap(i_arr[i], i_arr[min]);
}
}
3.直接插入排序 InsertSort
直接插入排序是一种简单有效的排序算法,其原理与扑克牌理牌原理类似,即将单个数据插入到已经排序好的有序序列中,当最后一个元素完成插入时,整个待排序列完成排序。
实现如下:
void my_sort::MySort::InsertSort(std::vector<int>& i_arr)
{
size_t i_arr_len = i_arr.size();
for (int i = 0; i < i_arr_len - 1; i++)
{
int j;
if (i_arr[i] > i_arr[i + 1])
{
int tmp = i_arr[i + 1];
for (j = i + 1; j > 0 && tmp < i_arr[j - 1]; j--)
{
i_arr[j] = i_arr[j - 1];
}
i_arr[j] = tmp;
}
}
}
4.希尔排序 ShellSort
希尔排序是插入排序的一种,是直接插入排序的改进版本。
实现如下:
void my_sort::MySort::ShellSort(std::vector<int>& i_arr)
{
size_t i_arr_len = i_arr.size();
for (int increment = i_arr_len / 2; increment > 0; increment /= 2)
{
for (int i = increment; i < i_arr_len; i++)
{
int tmp = i_arr[i];
int j;
for (j = i; j >= increment && i_arr[j - increment] > tmp; j -= increment)
i_arr[j] = i_arr[j - increment];
i_arr[j] = tmp;
}
}
}
5.归并排序 MergeSort
归并排序是典型的使用分治法的算法案例。其基本过程是将待排序列分割个单个元素,再将有序子序列合并,得到完全的有序序列。
递归实现如下:
void my_sort::MySort::MergeSort(std::vector<int>& i_arr)
{
MSort(i_arr, 0, i_arr.size() - 1);
}
void my_sort::MySort::MSort(std::vector<int>& SR, int Left, int Right)
{
if (Left == Right)
return;
int Center = (Left + Right) / 2;
MSort(SR, Left, Center);
MSort(SR, Center + 1, Right);
Merge(SR, Left, Center, Right);
}
void my_sort::MySort::Merge(std::vector<int>& SR, int Lpos, int mid, int Rpos)
{
std::vector<int> tmp(SR.size());
int i = Lpos;
int m = mid;
int n = Rpos;
int j, k, l;
for (j = m + 1, k = i; i <= m && j <= n; k++)
{
if (SR[i] < SR[j])
tmp[k] = SR[i++];
else
tmp[k] = SR[j++];
}
if (i <= m)
{
for (l = 0; l <= m - i; l++)
tmp[k + l] = SR[i + l];
}
if (j <= n)
{
for (l = 0; l <= n - j; l++)
tmp[k + l] = SR[j + l];
}
for (int idx = Lpos; idx <= Rpos; idx++)
SR[idx] = tmp[idx];
}
6.快速排序 QuickSort
快速排序算法别列为20世纪十大算法之一,其基本思想是通过一趟排序将要排序的数据分割成独立的两部分,再对这两部分进行快速排序,最终使待排序列变为有序序列。
递归实现如下:
void my_sort::MySort::QuickSort(std::vector<int>& i_arr, int low, int high)
{
int pivot;
if (low < high)
{
int tmp = i_arr[low];
int i = low;
int j = high;
while (i < j)
{
while (i < j && tmp <= i_arr[j])
j--;
my_sort::my_swap_val(i_arr[i], i_arr[j]);
//my_sort::my_swap(i_arr[i], i_arr[j]);
while (i < j && tmp >= i_arr[i])
i++;
my_sort::my_swap_val(i_arr[i], i_arr[j]);
//my_sort::my_swap(i_arr[i], i_arr[j]);
}
QuickSort(i_arr, low, i - 1);
QuickSort(i_arr, i + 1, high);
}
}
注:此处遇到一个问题,自己实现的swap函数有时会将元素变为0。检查的原因是swap函数是由位运算实现的,当交换参数为序列中的同一位置,运算之后的结果为0。
7.排序小结
ShellSort相当于InsertSort的升级,属插入排序类,
HeapSort相当于SelectionSort的升级,属选择排序类,
QuickSort相当于BubblSort的升级,属交换排序类。
复杂度分析:
排序算法 | 平均情况 | 最好情况 | 最坏情况 | 辅助空间 | 稳定性 |
---|---|---|---|---|---|
BubbleSort | O(n2) | O(n2) | O(n2) | O(1) | 稳定 |
SelectionSort | O(n2) | O(n2) | O(n2) | O(1) | 稳定 |
InsertSort | O(n2) | O(n2) | O(n2) | O(1) | 稳定 |
ShellSort | O(nlogn) ~ O(n2) | O(n1.3) | O(n2) | O(1) | 不稳定 |
HeapSort | O(nlogn) | O(nlogn) | O(nlogn) | O(1) | 不稳定 |
MergeSort | O(nlogn) | O(nlogn) | O(nlogn) | O(n) | 稳定 |
QuickSort | O(nlogn) | O(nlogn) | O(n2) | O(logn) ~ O(n) | 不稳定 |
8.code
my_sort.h
#ifndef MY_SORT_H
#define MY_SORT_H
#include <vector>
namespace my_sort {
class MySort
{
public:
void BubbleSort0(std::vector<int> &i_arr);
void BubbleSort(std::vector<int> &i_arr);
void SelectSort(std::vector<int> &i_arr);
void InsertSort(std::vector<int> &i_arr);
void ShellSort(std::vector<int> &i_arr);
// Merge Sort
void MergeSort(std::vector<int> &i_arr);
void MSort(std::vector<int> &SR, int Left, int Right);
void Merge(std::vector<int> &SR, int Lpos, int mid, int Rpos);
//
void QuickSort(std::vector<int> &i_arr, int low, int high);
};
void my_swap(int &a, int &b);
void my_swap_ptr(int * a, int * b);
void my_swap_vec(std::vector<int> &i_arr, int i, int j);
void my_swap_val(int &a, int &b);
}
#endif // !MY_SORT_H
main.cpp
#include <iostream>
#include <random>
#include <functional>
#include <time.h>
#include "my_sort.h"
#define print_arr(arr) \
for(auto &i:arr)\
cout << i<<" ";\
cout << endl;
using namespace std;
using namespace my_sort;
int main()
{
//int a = 1;
//int b = a;
//a ^= b;
//b ^= a;
//a ^= b;
//cout << a << " " << b << endl;
// 测试交换数组元素
int a[2] = { 1,3 };
a[1] ^= a[1];
a[1] ^= a[1];
a[1] ^= a[1];
std::default_random_engine generator(time(0));
std::uniform_int_distribution<int> dis(1, 100);
auto dice = std::bind(dis, generator);
const int NUM = 10;
vector<int> t_v;
for (int i = 0; i < NUM; i++)
t_v.emplace_back(dice());
print_arr(t_v);
my_sort::MySort sort;
//sort.BubbleSort(t_v);
//sort.SelectSort(t_v);
//sort.InsertSort(t_v);
//sort.ShellSort(t_v);
sort.MergeSort(t_v);
//sort.QuickSort(t_v, 0, t_v.size() - 1);
print_arr(t_v);
return 0;
}