排序(3)
这一章中我们将主要介绍下快速排序,并对这几章的排序算法进行总结。
1.快速排序
快速排序( Quick Sort) 的基本思想是:通过一趟排序将待排记录分割成独立的两部分,其中一部分记录的关键字均比另一部分记录的关键字小,则可分别对这两部分记录继续进行排序,以达到整个序列有序的目的。
#include<iostream>
#include<vector>
using namespace std;
void QuickSort(vector<int>& vec);//快速排序
void QSort(vector<int>& vec, int low, int high);
int Partition(vector<int>& vec, int low, int high);
int main()
{
int n,e;
vector<int> vec;
cout << "输入数据元素个数:" << endl;
cin >> n;
cout << "输入数据元素:" << endl;
for (int i = 0; i < n; i++)
{
cin >> e;
vec.push_back(e);
}
QuickSort(vec);
cout << "从小到大排序结果:" << endl;
for (int i = 0; i < n; i++)
{
cout << vec[i] << " ";
}
cout << endl;
system("pause");
return 0;
}
void QuickSort(vector<int>& vec)//快速排序
{
QSort(vec, 0, vec.size()-1);
}
void QSort(vector<int>& vec,int low ,int high)
{
int pivot;
if (low < high)
{
pivot = Partition(vec,low,high);
QSort(vec, low, pivot - 1);
QSort(vec, pivot + 1, high);
}
}
int Partition(vector<int>& vec, int low, int high)
{
int pivotkey;
pivotkey = vec[low];
while (low < high)
{
while (low < high&&vec[high] >= pivotkey)
high--;
swap(vec[low], vec[high]);
while (low < high&&vec[low] <= pivotkey)
low++;
swap(vec[low], vec[high]);
}
return low;
}
在VS上运行结果如下:
2.快速排序优化
2.1优化选取枢轴
取三个关键字先进行排序,将中间数作为枢轴, 一般是取左端、右端和中间三个数, 也可以随机选取。
int Partition(vector<int>& vec, int low, int high)
{
int pivotkey;
/*优化选取枢轴*/
int m = low + (high - low) / 2;
if (vec[low]>vec[high])
swap(vec[low], vec[high]);
if (vec[m] > vec[high])
swap(vec[m], vec[high]);
if (vec[m] > vec[low])
swap(vec[m], vec[low]);
pivotkey = vec[low];
while (low < high)
{
while (low < high&&vec[high] >= pivotkey)
high--;
swap(vec[low], vec[high]);
while (low < high&&vec[low] <= pivotkey)
low++;
swap(vec[low], vec[high]);
}
return low;
}
2.2优化不必要的交换
int Partition(vector<int>& vec, int low, int high)
{
int pivotkey;
/*优化选取枢轴*/
int m = low + (high - low) / 2;
if (vec[low]>vec[high])
swap(vec[low], vec[high]);
if (vec[m] > vec[high])
swap(vec[m], vec[high]);
if (vec[m] > vec[low])
swap(vec[m], vec[low]);
pivotkey = vec[low];
int e = pivotkey;//将枢轴关键字备份
while (low < high)
{
while (low < high&&vec[high] >= pivotkey)
high--;
//swap(vec[low], vec[high]);
e = vec[high];//采用替换代替交换
while (low < high&&vec[low] <= pivotkey)
low++;
//swap(vec[low], vec[high]);
e = vec[low];//采用替换代替交换
}
vec[low] = e;//替换回去
return low;
}
2.3优化小数组时的排序方案
如果数组非常小,其实快速排序反而不如直接插入排序来得更好(直接插入是简单排序中性能最好的)。
#define MAX_SORT 7
void QSort(vector<int>& vec,int low ,int high)
{
int pivot;
//if (low < high)
if ((high-low)>MAX_SORT)
{
pivot = Partition(vec,low,high);
QSort(vec, low, pivot - 1);
QSort(vec, pivot + 1, high);
}
else
InsertSort(vec);
}
void InsertSort(vector<int>& vec)//直接插入排序
{
for (int i = 1; i < vec.size(); i++)
{
int e,j;
if (vec[i - 1] > vec[i])
{
e = vec[i];
for (j = i - 1; j >= 0 && vec[j] > e; j--)
vec[j + 1] = vec[j];
vec[j + 1] = e;
}
}
}
2.4优化递归操作
如果能减少递归,将会大大提高性能。
void QSort(vector<int>& vec,int low ,int high)
{
int pivot;
//if (low < high)
if ((high-low)>MAX_SORT)
{
/*pivot = Partition(vec,low,high);
QSort(vec, low, pivot - 1);
QSort(vec, pivot + 1, high);*/
/*尾递归优化*/
while (low < high)
{
pivot = Partition(vec, low, high);
QSort(vec, low, pivot - 1);
low = pivot + 1;
}
}
else
InsertSort(vec);
}
在VS上运行结果如下:
3.排序总结
排序方法 | 平均情况 | 最好情况 | 最坏情况 | 辅助空间 | 稳定性 |
---|---|---|---|---|---|
冒泡排序 | O(n2) O ( n 2 ) | O(n) O ( n ) | O(n2) O ( n 2 ) | O(1) O ( 1 ) | 稳定 |
简单选择排序 | O(n2) O ( n 2 ) | O(n2) O ( n 2 ) | O(n2) O ( n 2 ) | O(1) O ( 1 ) | 稳定 |
直接插入排序 | O(n2) O ( n 2 ) | O(n) O ( n ) | O(n2) O ( n 2 ) | O(1) O ( 1 ) | 稳定 |
希尔排序 | O(nlogn) O ( n l o g n ) ~ O(n2) O ( n 2 ) | O(n2/3) O ( n 2 / 3 ) | O(n2) O ( n 2 ) | O(1) O ( 1 ) | 不稳定 |
堆排序 | O(nlogn) O ( n l o g n ) | O(nlogn) O ( n l o g n ) | O(nlogn) O ( n l o g n ) | O(1) O ( 1 ) | 不稳定 |
归并排序 | O(nlogn) O ( n l o g n ) | O(nlogn) O ( n l o g n ) | O(nlogn) O ( n l o g n ) | O(n) O ( n ) | 稳定 |
快速排序 | O(nlogn) O ( n l o g n ) | O(nlogn) O ( n l o g n ) | O(n2) O ( n 2 ) | O(nlogn) O ( n l o g n ) ~ O(n) O ( n ) | 不稳定 |
版权声明:本文不是「本站」原创文章,版权归原作者所有 | 原文地址: