#include<iostream>
#include<vector>
#include<string>
#include<algorithm>
#include <ctime>
#include <queue>
#include<stack>
using namespace std;
class Sort {
public:
void print(vector<int>nums, string sort) {
cout << sort << ":";
for (int i : nums) {
cout << i << " ";
}
}
void HaoSort(vector<int>& nums, int n) {
for (int i = 0; i < n - 1; i++) {
for (int j = i + 1; j < n; j++) {
if (nums[i] > nums[j]) swap(nums[i], nums[j]);
}
}
}
//冒泡排序
void BubbleSort(vector<int>& nums, int n) {
for (int i = 0; i < n; i++) {
int exchange = 0;
for (int j = 1; j < n - i; j++) {
if (nums[j] < nums[j - 1]) {
swap(nums[j - 1], nums[j]);
exchange = 1;
}
}
if (exchange == 0) break;//说明已经有序 此时最好情况下为O(N)
}
}
//直接选择排序(优化排序,一次找两个数)
//O(N*N)
void SelectSort(vector<int>& nums, int n) {
int begin = 0;
int end = n - 1;
while (begin < end) {
int mini = begin;//当前最小数的下标
int maxi = begin;//当前最大数的下标
for (int i = begin; i <= end; i++) {
if (nums[i] < nums[mini]) mini = i;
if (nums[i] > nums[maxi]) maxi = i;
}
swap(nums[mini], nums[begin++]);
if (maxi == begin) maxi = mini;//如果begin跟maxi重叠 需要修正maxi
swap(nums[maxi], nums[end--]);
}
}
//插入排序
//O(n^2)
void InsertSort(vector<int>& nums, int n) {
for (int i = 1; i < n; i++) {
int end = i;
while (end) {
if (nums[end - 1] > nums[end]) {//后移 并且end前移
swap(nums[end - 1], nums[end]);
end--;
}
else{
break;
}
}
}
}
//希尔排序
//改进的插入排序算法
//分组排序 预排序
//时间复杂度:O(N*logN)
//平均时间复杂度:O(log1.3N)
void ShellSort(vector<int>& nums, int n) {
int gap = n;
while (gap > 1) {
gap = gap / 3 + 1;//调整希尔变量 O(log3N)
//当gap很大时,下面预排序时间复杂度O(N)
//当gap很小时,这时已经接近有序 预排序时间复杂度O(N)
for (int i = gap; i < n; i++) {
int end = i;
while (end>=gap) {
if (nums[end-gap] > nums[end]) {//后移 并且end前移
swap(nums[end], nums[end-gap]);
end-=gap;
}
else {
break;
}
}
}
}
}
//堆排序
//O(n*logn)
//堆的两个特性
//结构性:用数组表示的完全二叉树
//有序性:任一节点的关键字是其子树所有节点的最大值(或最小值)
//“最大堆”,也称为“大顶堆”:最大值 所有parent大于等于child
//“最小堆”,也称为“小顶堆”:最小值 所有parent小于等于child
void AdjustDown(vector<int>& nums, int n, int root) {
int parent = root;
int child = parent * 2 + 1;//默认为左孩子
while (child < n) {
//1.选出左右孩子中大的一个
if (child + 1 < n && nums[child + 1] > nums[child]) {
child++;
}
if (nums[child] > nums[parent]) {
swap(nums[child], nums[parent]);
parent = child;
child = parent * 2 + 1;
}
else {
break;
}
}
}
void HeapSort(vector<int>& nums, int n) {
//建堆
for (int i = (n - 1 - 1) / 2; i >= 0; i--) {
AdjustDown(nums, n, i);
}
int end = n - 1;
while (end) {
swap(nums[0], nums[end]);
AdjustDown(nums, end--, 0);
}
}
//基数排序
//O(n*k)
void RadixSort(vector<int>& nums, int n) {
//定义临时二维数组表示十个堆
vector<vector<int>> temp(10, vector<int>(n));
//定义一个一维数组 记录在temp中相应的数组中存放数字的数量
vector<int> counts(10);
//找到数组中最大数
int max = *max_element(nums.begin(), nums.end());
//计算最大数字是几位数 获得轮回次数
int maxLength = (to_string)(max).size();
for (int i = 0, k = 1; i < maxLength; i++, k *= 10) {
//把每一个数字分别计算余数(个位十位百位.....)
for (int j = 0; j < n; j++) {
//计算余数(个位十位百位.....) num = 0~9
int num = nums[j] / k % 10;
temp[num][counts[num]] = nums[j];
//记录数量
counts[num]++;
}
//记录取元素需要放的位置
int index = 0;
//把数字取出来
for (int j = 0; j < 10; j++) {
//循环取出元素
for (int w = 0; w < counts[j]; w++) {
nums[index++] = temp[j][w];
}
counts[j] = 0;
}
}
}
//计数排序:适用范围具有局限性
//非比较排序
//适用于范围集中的整数集合
//时间复杂度:O(n+range)
//空间复杂度:O(range)
void CountSort(vector<int>&nums,int n) {
int max = *max_element(nums.begin(), nums.end());
int min = *min_element(nums.begin(), nums.end());
int range = max - min+1;
vector<int> count(range,0);
for (int i = 0; i < n; i++) {
count[nums[i] - min]++;
}
int index = 0;
for (int i = 0; i < range; i++) {
while (count[i]--) {
nums[index++] = i + min;
}
}
}
//三数取中
int GetMidIndex(vector<int> &nums, int left, int right) {
int mid = (left + right) >> 1;
if (nums[left] > nums[mid]) swap(nums[left], nums[mid]);
if (nums[right] < nums[mid]) swap(nums[right], nums[mid]);
return mid;
}
//快速排序
//O(N*logN)
//挖坑法
//左右指针
int PartSort1(vector<int>&nums,int left,int right) {
int begin = left, end = right;
int pivot = GetMidIndex(nums, left, right);//坑位
int key = nums[pivot];//关键值
//单趟排序O(N)
while (begin < end) {
//右边找小
while (begin < end && nums[end] >= key) end--;
nums[pivot] = nums[end];//填坑位
pivot = end;//挖坑位
//左边找大
while (begin < end && nums[begin] <= key) begin++;
nums[pivot] = nums[begin];
pivot = begin;
}
nums[begin] = key;
return begin;
}
//左右指针
int PartSort2(vector<int>& nums, int left, int right) {
int begin = left, end = right;
int index = GetMidIndex(nums, left, right);//坑位
swap(nums[left], nums[index]);
int key = nums[left];//关键值
//单趟排序
while (begin < end) {
while (begin < end && nums[end] >= key) {
end--;
}
while (begin < end&&nums[begin] <= key) {
begin++;
}
swap(nums[begin], nums[end]);
}
swap(nums[begin], nums[left]);
return begin;
}
int PartSort3(vector<int>& nums, int left, int right) {
int index = GetMidIndex(nums, left, right);
swap(nums[index], nums[left]);
int pivot = nums[left];
int prev = left;
int cur = left+1;
while (cur <= right) {
if (nums[cur] <pivot) {
++prev;
swap(nums[prev], nums[cur]);
}
++cur;
}
swap(nums[prev], nums[left]);
return prev;
}
//时间复杂度:O(N*logN)
void QuickSort(vector<int>& nums, int left, int right) {
if (right <= left) return;
int pivot = PartSort3(nums, left, right);
//分治递归
//[left,right]
//[left,pivot-1] pivot [pivot+1,right]
QuickSort(nums,pivot+1, right);//右边
QuickSort(nums,left, pivot-1);//左边XXX
//if (pivot - 1 - left > 10) {
// QuickSort(nums, pivot + 1, right);
//}
//else{
// sort(nums.begin() + left, nums.begin() + pivot);
//}
//if (right - (pivot + 1) > 10) {
// QuickSort(nums, left, pivot - 1);
//}
//else {
// sort(nums.begin() + pivot + 1, nums.begin() + right);
//}
}
//非递归qsort
void QuickSortNond(vector<int>& nums,int n){
stack<int> s;
s.push(n - 1);
s.push(0);
while (s.size()) {
int left = s.top();
s.pop();
int right = s.top();
s.pop();
int keyi = PartSort2(nums, left, right);
if (left < keyi) {
s.push(keyi);
s.push(left);
}
if (right > keyi + 1) {
s.push(right);
s.push(keyi+1);
}
}
}
//归并排序
//O(N*logN)
void MergeSort(vector<int>& nums,int left,int right) {
if (left >= right) return;
int mid = (right + left) >> 1;
//递归拆分
//[left,mid] [mid+1,right]
MergeSort(nums, left, mid);//左半部分
MergeSort(nums, mid+1, right);//右半部分
//合并
//队列顺序存储元素
queue<int> q;
//左部分
int begin1 = left, end1 = mid;
//右部分
int begin2 = mid + 1, end2 = right;
//左右部分对比 元素顺序入队列
while (begin1 <= end1 && begin2 <= end2) {
if (nums[begin1] < nums[begin2]){
q.push(nums[begin1++]);
}
else {
q.push(nums[begin2++]);
}
}
//剩余元素入队列
while (begin1 <= end1) {
q.push(nums[begin1++]);
}
while (begin2 <= end2) {
q.push(nums[begin2++]);
}
//copy回去
int index = left;
while (q.size()) {
nums[index++] = q.front();
q.pop();
}
}
//非递归
void MergeSortNond(vector<int>& nums, int n) {
int gap = 1;//每组数据个数
//队列顺序存储元素
queue<int> q;
while (gap < n) {
for (int i = 0; i < n; i += 2 * gap) {
int begin1 = i, end1 = i + gap-1;
int begin2 = i + gap, end2 = i + 2 * gap - 1;
//归并过程中右区间不存在
//此时直接结束循环
if (begin2 >= n) break;
//归并过程中右区间存在一部分
if (end2 >= n) end2 = n - 1;
//左右部分对比 元素顺序入队列
while (begin1 <= end1 && begin2 <= end2) {
if (nums[begin1] < nums[begin2]) {
q.push(nums[begin1++]);
}
else {
q.push(nums[begin2++]);
}
}
//剩余元素入队列
while (begin1 <= end1) {
q.push(nums[begin1++]);
}
while (begin2 <= end2) {
q.push(nums[begin2++]);
}
}
//每一轮copy回去
int index = 0;
while (q.size()) {
nums[index++] = q.front();
q.pop();
}
gap *= 2;//合并
}
}
//排序的性能对比
void TestOP() {
srand(time(0));
const int N = 100000;
vector<int> nums1(N);
vector<int> nums2(N);
vector<int> nums3(N);
vector<int> nums4(N);
vector<int> nums5(N);
vector<int> nums6(N);
vector<int> nums7(N);
vector<int> nums8(N);
vector<int> nums9(N);
for (int i = 0; i < N; i++) {
nums1[i] = rand();
nums2[i] = nums1[i];
nums3[i] = nums1[i];
nums4[i] = nums1[i];
nums5[i] = nums1[i];
nums6[i] = nums1[i];
nums7[i] = nums1[i];
nums8[i] = nums1[i];
nums9[i] = nums1[i];
}
int begin = clock();
SelectSort(nums1, N);
int end = clock();
cout << "SelectSort:" << end - begin << endl;
begin = clock();
BubbleSort(nums8, N);
end = clock();
cout << "BubbleSort:" << end - begin << endl;
begin = clock();
InsertSort(nums2, N);
end = clock();
cout << "InsertSort:" << end - begin <<endl;
begin = clock();
ShellSort(nums3, N);
end = clock();
cout << "ShellSort:" << end - begin << endl;
begin = clock();
HeapSort(nums4, N);
end = clock();
cout << "HeapSort:" << end - begin << endl;
begin = clock();
RadixSort(nums5, N);
end = clock();
cout << "RadixSort:" << end - begin<<endl;
begin = clock();
QuickSort(nums6,0, N-1);
end = clock();
cout << "QuickSort:" << end - begin << endl;
begin = clock();
MergeSort(nums7, 0, N - 1);
end = clock();
cout << "MergeSort:" << end - begin << endl;
begin = clock();
CountSort(nums8,N);
end = clock();
cout << "CountSort:" << end - begin << endl;
}
};
int main() {
Sort sort;
vector<int> nums = { 6,5,2,7,8,3,1,9,4,0};
int n = nums.size();
//sort.InsertSort(nums,n);
//sort.print(nums,"InsertSort");
//sort.HeapSort(nums,n);
//sort.RadixSort(nums, n);
//sort.SelectSort(nums, n);
//sort.ShellSort(nums, n);
//sort.print(nums, "ShellSort:");
//sort.HaoSort(nums, n);
//sort.print(nums, "Haosort:");
//sort.BubbleSort(nums, n);
//sort.print(nums, "BubbleSort:");
//sort.QuickSort(nums, 0,n-1);
//sort.print(nums, "QuickSort:");
//sort.MergeSort(nums,0,n-1);
//sort.print(nums, "MergeSort:");
//sort.QuickSortNond(nums,n);
//sort.print(nums, "QuickSortNond:");
//sort.MergeSortNond(nums,n);
//sort.print(nums, "MergeSortNond:");
//sort.CountSort(nums,n);
//sort.print(nums, "CountSort:");
sort.TestOP();
return 0;
}
十万数据排序时间对比:
SelectSort:19565
BubbleSort:55163
InsertSort:29196
ShellSort:40
HeapSort:35
RadixSort:13
QuickSort:19
MergeSort:109
CountSort:3