快速排序
基本思想:
快速排序是交换排序的一种。通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据小,然后,依次按此方法分割排序,以此达到整个数据变成有序序列。
时间复杂度:
O(N*logN) (最坏情况为O(N^2),即为每次选取的key值均为最大或最小;最优情况为O(N*logN),因为对于快排来说,每次都取到最大或最小的key值情况非常少,几乎不可能发生,所以快排时间复杂度为O(N*logN))
空间复杂度:
O(logN)
稳定性:
快速排序是不稳定算法
性能:
快速排序是实用性非常高的排序算法,实现方法也很多,同时快排也有很多需要优化的地方。
比如:
1.排序时,每次选取的key值越接近数据中间位置,排序越快,可以通过三数取中方法来实现。
2.当待排数据特别多,使用递归方法时,每层建立栈帧结构,函数栈帧开销太大,并且有可能出现栈溢出问题,此时可以给小区间使用其他排序算法,比如直接排序,借此来减少函数栈帧开销。
快排动图:
递归代码实现:
#include <iostream>
#include <Windows.h>
#include <assert.h>
using namespace std;
int PartSort(int* arr, int left, int right);
//快速排序,递归实现
void QuickSort(int* arr, int left, int right)
{
if (left >= right)
{
return; //递归出口
}
int div = PartSort(arr, left, right);
QuickSort(arr, left, div - 1);
QuickSort(arr, div + 1, right);
}
int PartSort(int* arr, int left, int right) //单趟排序,前后指针法
{
assert(arr);
int cur = left;
int prev = left - 1;
int key = arr[right];
while (cur < right) //均为下标
{
if (arr[cur] < key)
{
++prev;
if (prev != cur)
{
swap(arr[prev], arr[cur]);
}
}
++cur;
}
//此时出了循环之后,cur==right
++prev;
swap(arr[prev], arr[right]);
return prev; //返回一个下标,以此作为之后循环分组的依据
}
void Print(int* arr, int len) //打印
{
for (int i = 0; i < len; ++i)
{
cout << arr[i] << "->";
}
cout << endl;
}
#include "QuickSort.h"
void TestQuickSort()
{
int arr[] = { 2, 3, 6, 7, 666, 777, 99, 67, 98, 1, 33, 3333, 28, 7777, 4, 5 };
int len = sizeof(arr) / sizeof(arr[0]);
cout << "未排序数据:" << "";
Print(arr, len);
QuickSort(arr, 0, len - 1);
cout << "已排序数据:" << "";
Print(arr, len);
}
int main()
{
TestQuickSort();
system("pause");
return 0;
}
非递归实现:
#include <iostream>
#include <Windows.h>
#include <stack>
#include <assert.h>
using namespace std;
int PartSort(int* arr, int left, int right);
//快速排序,非递归实现
void QuickSort(int* arr, int left, int right)
{
if (arr == NULL)
{
return;
}
stack<int> tty;
tty.push(right);
tty.push(left);
while (!tty.empty())
{
int start = tty.top();
tty.pop();
int end = tty.top();
tty.pop();
int div = PartSort(arr, start, end);
if (start < div - 1)
{
tty.push(div - 1);
tty.push(start);
}
if (div + 1 < end)
{
tty.push(end);
tty.push(div + 1);
}
}
}
int PartSort(int* arr, int left, int right) //单趟排序,前后指针法
{
assert(arr);
int cur = left;
int prev = left - 1;
int key = arr[right];
while (cur < right) //均为下标
{
if (arr[cur] < key)
{
++prev;
if (prev != cur)
{
swap(arr[prev], arr[cur]);
}
}
++cur;
}
//此时出了循环之后,cur==right
++prev;
swap(arr[prev], arr[right]);
return prev; //返回一个下标,以此作为之后循环分组的依据
}
void Print(int* arr, int len) //打印
{
for (int i = 0; i < len; ++i)
{
cout << arr[i] << "->";
}
cout << endl;
}