1.快排的思想
以这个数组为例:
快排的思想是分治策略,先找到一个基准值,给基准值找到一个合适的位置,使得基准值左边的值都小于基准值,右边的值都大于基准值。这样再分别对基准值左边和右边进行快速排序,一直到数组完全有序。既然要使得基准值左边的值都小于基准值,基准值右边的值都大于基准值,那么就避免不了数据的挪动。
让一个指针right指向数组最后一个位置,另一个指针left指向数组开始。从right开始,让数组中right的值和基准值比较,如果比基准值大,那么就right-1,一直到找到一个比基准值小的值,放到数组的left下标的位置里。接着从left开始,让数组中left的值和基准值进行比较,如果比基准值小,那么left+1;一直到找到一个比基准值大的数,放到right下标中。再重复此过程,一直到left与right相遇,就是基准值该放的位置;
这个时候left与right相遇,可以很清楚的看到,相遇位置的左边都是比12小的值,右边都是比12大的值,所以将基准值12插入到这个位置即可
然后还是同样的思想, 12左边进行一次快排,右边进行一次快排,数组就完全有序了。
我再展示一下12左边的快排:
还是从right开始,找比0小的数放入arr[left]中,再从left开始找比0大的数放入arr[right]中,一直到left与right相遇。
再来看0的左边,没有元素。接着看右边,在进行快排:
排序完成后是这样,7的左边和右边都只有一个元素,那就是有序的,至此,12的左边以及排序完了。再接着排序12的右边。
快排的时间复杂度为O(nlogn),空间复杂度为O(logn)。由于一直存在跳跃交换,所以快排是一个不稳定的算法。
2.快排的递归实现
快排的递归实现比较简单,一直重复上述操作即可:
int Partition(int* arr, int left, int right)
{
int tmp = arr[left];
while (left < right)
{
while (left<right && arr[right]>tmp)
{
--right;
}
arr[left] = arr[right];
while (left < right && arr[left] <= tmp)
{
++left;
}
arr[right] = arr[left];
}
arr[left] = tmp;
return left;
}
void Quick(int* arr, int left, int right)
{
if (left < right)
{
int par = Partition(arr, left, right);
if (left < par - 1)
{
Quick(arr, left, par - 1);
}
if (right > par + 1)
{
Quick(arr, par + 1, right);
}
}
}
int main()
{
int arr[] = { 56,88,14,26,99,556,47,556,324,13,5,842,1 };
int len = sizeof(arr) / sizeof(arr[0]);
Quick_Stack(arr, 0, len - 1);
for (int i = 0; i < len; ++i)
{
cout << arr[i] << " ";
}
}
3.快排的非递归实现
快速排序的非递归实现,需要用到辅助工具——栈
可以将第一次基准值排完后的左边left与right和右边的left与right都放入栈中,然后边出栈边排序,排序的话又得入栈,然后又出栈又排序。这样就模拟了递归的方法,实现快排!
下面是快排非递归实现的代码:
int Partition(int* arr, int left, int right)
{
int tmp = arr[left];
while (left < right)
{
while (left<right && arr[right]>tmp)
{
--right;
}
arr[left] = arr[right];
while (left < right && arr[left] <= tmp)
{
++left;
}
arr[right] = arr[left];
}
arr[left] = tmp;
return left;
}
void Quick_Stack(int* arr, int left, int right)
{
stack<int> st;
if (left < right)
{
int par = Partition(arr, left, right);
if (left < par - 1)
{
st.push(left);
st.push(par - 1);
}
if (right > par + 1)
{
st.push(par + 1);
st.push(right);
}
}
while (!st.empty())
{
int l = 0;
int r = 0;
r = st.top();
st.pop();
l = st.top();
st.pop();
int par = Partition(arr, l, r);
if (l < par - 1)
{
st.push(l);
st.push(par - 1);
}
if (r > par + 1)
{
st.push(par + 1);
st.push(r);
}
}
}
int main()
{
int arr[] = { 56,88,14,26,99,556,47,556,324,13,5,842,1 };
int len = sizeof(arr) / sizeof(arr[0]);
Quick_Stack(arr, 0, len - 1);
for (int i = 0; i < len; ++i)
{
cout << arr[i] << " ";
}
}
感谢阅读!