快速排序是Hoare于1962提出的一种二叉树结构的交换排序方法,其基本思想为:任取待排序元素序列种某个元素作为基准值,按照该排序码将排序集合分割为两子序列,左子序列种所有元素的值均小于基准值,右子序列中所有元素的值均大于基准值,然后两个子序列重复该过程,知道所有元素均大于基准值,然后左右子序列重复该过程,直到所有元素都排列在相应的位置元素上
`void QuickSort(int arr[], int left, int right)
{
if (left >= right)
return;
//按照基准值对数组的[left,right]区间进行划分
int ret = partion(arr, left, right);
//递归后将数组排成了[left,ret-1]和[ret+1,right]
//递归排[left,ret-1]
QuickSort(arr, left, ret - 1);
//递归排[ret+1,right]
QuickSort(arr, ret + 1, right);
}
以上就是快速排序的主框架,这与二叉树的前序遍历有些相似,接下来就只用思考如何实现partion过程就可以了
为什么相遇的位置要比key要小?
这里要分为两种情况
void swap(int arr[], int x, int y)
{
int tmp = arr[x];
arr[x] = arr[y];
arr[y] = tmp;
}
int partion(int arr[], int left, int right)
{
//将基准值的下标记录下来是为了方便最后进行交换
int key = left;
while (right > left)
{
//前置条件right>left是为了防止越界
while (right > left && arr[right] >= arr[key])
{
right--;
}
while (right > left && arr[left] <= arr[key])
{
left++;
}
swap(arr, right, left);
}
swap(arr, key, left);
return left;
}
void QuickSort(int arr[], int left, int right)
{
if (left >= right)
return;
//按照基准值对数组的[left,right]区间进行划分
int ret = partion(arr, left, right);
//递归后将数组排成了[left,ret-1]和[ret+1,right]
//递归排[left,ret-1]
QuickSort(arr, left, ret - 1);
//递归排[ret+1,right]
QuickSort(arr, ret + 1, right);
}
int partion(int arr[], int left, int right)//挖坑法
{
int k = arr[left];
//此时left所指向位置为'坑'
while (right > left)
{
while (right > left && arr[right] >= k)
{
right--;
}
arr[left] = arr[right];
//此时right所指向位置更新为'坑'
while (right > left && arr[left] <= k)
{
left++;
}
arr[right] = arr[left];
//此时left所指向位置更新为'坑'
}
arr[left] = k;
return left;
}
void QuickSort(int arr[], int left, int right)
{
if (left >= right)
return;
//按照基准值对数组的[left,right]区间进行划分
int ret = partion(arr, left, right);
//递归后将数组排成了[left,ret-1]和[ret+1,right]
//递归排[left,ret-1]
QuickSort(arr, left, ret - 1);
//递归排[ret+1,right]
QuickSort(arr, ret + 1, right);
}
void swap(int arr[], int x, int y)
{
int tmp = arr[x];
arr[x] = arr[y];
arr[y] = tmp;
}
int partion(int arr[], int left, int right)
{
int key = left;
int prev = left;
int cur = prev + 1;
while (cur <= right)
{
if (arr[cur] < arr[key])
{
prev++;
swap(arr, prev, cur);
}
cur++;
}
swap(arr, key, prev);
return prev;
}
void QuickSort(int arr[], int left, int right)
{
if (left >= right)
return;
//按照基准值对数组的[left,right]区间进行划分
int ret = partion(arr, left, right);
//递归后将数组排成了[left,ret-1]和[ret+1,right]
//递归排[left,ret-1]
QuickSort(arr, left, ret - 1);
//递归排[ret+1,right]
QuickSort(arr, ret + 1, right);
}
快速排序的非递归实现使用了栈来模拟递归的过程。其基本思路如下:
int partion(int arr[], int left, int right)//挖坑法
{
int k = arr[left];
while (right > left)
{
while (right > left && arr[right] >= k)
{
right--;
}
arr[left] = arr[right];
while (right > left && arr[left] <= k)
{
left++;
}
arr[right] = arr[left];
}
arr[left] = k;
return left;
}
void QuickSort(int arr[], int left, int right)
{
stack<int>st;
//将左右两个区间放入栈中
st.push(left);
st.push(right);
while (!st.empty())
{
right = st.top();
st.pop();
left = st.top();
st.pop();
if (left >= right)
continue;//筛选掉不合规范的区间
int ret = partion(arr, left, right);
//以基准值为分割点,形成两部分[left,ret-1]和[ret+1,right]
st.push(left);
st.push(ret - 1);
st.push(ret + 1);
st.push(right);
}
}
通过使用栈来保存每个待排序子序列的起始位置和结束位置,非递归的快速排序可以避免递归调用带来的额外开销,提高排序的效率。