最常用的排序算法,速度通常也是最快的。
时间复杂度:O(n*logn)
最坏:O(n^2)
空间复杂度:O(n*lgn)
不稳定(比如 5 3 3 4 3 8 9 10 11 这个序列,在中枢元素5和3交换就会把元素3的稳定性打乱)
#include
#include
#include
#define MAX_LENGTH_INSERT_SORT 7
void m_swap(SqList *L,int low,int high);
int Partition(SqList *L,int low,int high);
void QSort(SqList *L ,int low , int high);
void QuickSort(SqList *L);
typedef struct SqList
{
int r[10] = {1,8,12,3,14,5,13,15,23,45};
int length = 9;
}SqList;
using namespace std;
int main()
{
SqList L;
for(int i = 0; i < 10; i++)
cout << L.r[i] << " ";
cout << endl;
QuickSort(&L);
for(int i = 0; i < 10; i++)
cout << L.r[i] << " ";
}
m_swap交换二者的数值
void m_swap(SqList *L,int low,int high)
{
int t = L->r[low];
L->r[low] = L->r[high];
L->r[high] = t;
}
Partition 选择中间值
int Partition(SqList *L,int low,int high)
{
int pivotkey;
pivotkey = L->r[low];
while(low < high)
{
while(low < high && L->r[high] >= pivotkey)
high--;
m_swap(L,low,high);
while(low < high && L->r[low] <= pivotkey)
low++;
m_swap(L,low,high);
}
return low;
}
优化选取中间轴: 取中间值越准确,节省时间越少。
int Partition(SqList *L,int low,int high)
{
int pivotkey;
int m = low + (high - low) / 2; //求出数组中间值
if(L->r[low] > L->r[high]) //最小坐标跟最大坐标比较小的放在最右面
swap(L,low,high);
if(L->r[m] > L->r[high]) //中间坐标跟最大比较大的放在最左面
swap(L,high,m);
if(L->r[m] > L->r[low]) //将数值中间值放在low上。
swap(L,m,low);
pivotkey = L->r[low];
while(low < high)
{
while(low < high && L->r[high] >= pivotkey)
high--;
m_swap(L,low,high);
while(low < high && L->r[low] <= pivotkey)
low++;
m_swap(L,low,high);
}
return low;
}
递归分别对前后做出排序
void QSort(SqList *L ,int low , int high)
{
int pivot;
if(low < high)
{
pivot = Partition(L,low,high);
QSort(L,low,pivot - 1);
QSort(L,pivot + 1,high);
}
}
void QuickSort(SqList *L)
{
QSort(L,0,L->length);
}
优化不必要的交换
int Partition(SqList *L,int low,int high)
{
int pivotkey;
pivotkey = L->r[low];
L->r[0] = pivotkey; //将取出的关键字备份
while(low < high)
{
while(low < high && L->r[high] >= pivotkey)
high--;
L->r[low] = L->r[high];//采用替换的方式而不是交换的方式
while(low < high && L->r[low] <= pivotkey)
low++;
L->r[high] = L->r[low];
}
L->r[low] = L->r[0];//替换完之后,将中间值放回去。
return low;
}
快速排序对小数组排序的复杂度不如插入排序,所以我们可以加一个判断
如果是小数组的排序,直接使用插入排序等其他排序,小数组的定义范围
在 ( high - low ) 小于7到50之间的数由实际情况定。这样就能保证最大
的效率完成排序工作。
优化递归
void QSort1(SqList *L ,int low , int high)
{
int pivot;
if( (high - low) > MAX_LENGTH_INSERT_SORT)//判断是否需要快排
{
while(low < high)
{
pivot = Partition(L,low,high);
QSort(L,low,pivot - 1);
low = pivot + 1;
}
}
else
InsertSort(L); // 插入排序小数据排序应该考虑的排序
}