快速排序的优化、复杂度以及使用情况
#include <stdio.h>
#include <iostream>
#include <vector>
using namespace std;
#if 0
快速排序是最慢的冒泡排序的升级 他们都属于交换排序类
即它是通过不断比较和移动交换来实现排序的,只不过它的实现
增大了记录的比较和移动的距离,将关键字较大的记录从前面直
接移动到后面,关键字较小的记录从后面直接移动到前面,从而
减少了总的比较次数和移动交换次数
快速排序的基本思想是:通过一趟排序记录分割成独立的俩部分,
其中一部分记录的关键字均比另一部分记录的关键字小,则可分
别对这俩部分记录继续进行排序,以达到整个序列有序的目的
本质是通过一次次确定中轴的位置,并根据此位置进行分区,
再确定分区中轴的位置一步步排序的
类似一次次通过二分法来确定顺序
时间复杂度:O[nlogn]
空间复杂度:O[logn] 主要是递归造成的栈空间的使用
适用情况:对于非常大的数组用起来会好 对于数组非常小则不如直接插入排序更好
#endif
int Partition(vector<int> & v,int low,int high)
{
//改进方法:三值取中法 比较首中尾三个数据取合适值
int mid = low + (high - low) / 2; //计算数组中间下标
if (v[low] > v[high])
swap(v[low], v[high]); //交换首尾数据保证首端小
if (v[mid]>v[high])
swap(v[mid], v[high]); //交换中尾数据保证中间小
if (v[mid]>v[low])
swap(v[mid], v[low]); //交换首中数据保证下标为low的是中轴
int middleValue = v[low]; //用表中第一个记录作为中轴
while (low < high) //从表俩侧向中轴交替扫描
{
while (low < high&&v[high] >= middleValue) //从表尾端开始找一个比中轴小的数
high--; //尾端前移
swap(v[low], v[high]); //将中轴和在尾端开始比中轴小的数交换
while (low < high&&v[low] <= middleValue) //从表头端找一个比中轴大的数
low++;
swap(v[low], v[high]); //将在尾端的中轴和头端小于中轴的数进行交换
}
return low; //返回中轴所在位置 low high都可以 此时俩者重合
}
//优化后的方法 优化不必要的交换
int Partition1(vector<int> & v, int low, int high)
{
int mid = low + (high - low) / 2;
if (v[low] > v[high])
swap(v[low], v[high]);
if (v[mid]>v[high])
swap(v[mid], v[high]);
if (v[mid]>v[low])
swap(v[mid], v[low]);
int pivotkey = v[low];
//将中轴备份 也可以通过设置哨兵的方式不将数组v[0]的
//位置放入数据 将中轴备份给v[0]
int i = pivotkey;
while (low < high)
{
while (low < high&&v[high] >= pivotkey)
high--;
v[low] = v[high]; //采用赋值而不是交换
while (low < high&&v[low] <= pivotkey)
low++;
v[high] = v[low]; //采用赋值而不是交换
}
v[low] = i; //将中轴赋值给当前位置
return low; //返回中轴所在位置 low high都可以 此时俩者重合
}
void QuickSort(vector<int>& v, int low, int high)
{
if (low < high) //判断至少存在俩个元素
{
int mid = Partition(v, low, high); //或者用Partition1
QuickSort(v, low, mid - 1); //对低子表递归排序
QuickSort(v, mid + 1, high);//对高子表递归排序
}
}
//递归的优化 实施尾递归的优化 采用迭代方法缩减栈深度
void QuickSort1(vector<int>& v, int low, int high)
{
int pivot;
while (low < high)
{
pivot = Partition(v, low, high); //或者用Partition1
QuickSort1(v, low, pivot - 1); //对低子表递归排序
low = pivot + 1;//尾递归
}
}
int main(int argc,char *argv[])
{
vector<int> v = { 50, 10, 90, 30, 70, 40, 80, 60, 20 };
//哨兵模式
vector<int> v1 = { 0, 50, 10, 90, 30, 70, 40, 80, 60, 20 };
//参数含义是 数组 数组下标首位 数组下标末位
QuickSort1(v, 0, v.size()-1);
for (auto c : v)
{
cout << c << endl;
}
return 0;
}