快速排序的中心思想在于左右指针的循环查找以及,基准设定之后的挖坑填坑。
快速排序复杂,理解难度高。算法涉及广泛。
算法核心使用递归法,所以需要递归终止条件。
递归函数需要的形参有,数组和左右指针。
quickSort(int a[],int leftP,int rightP)
第一遍递归
设定基准
// 基准为左边第一位元素
int X=a[leftP];
形参的指针赋值给新指针变量
必须新设定指针变量,因为需要保证形参不变,作为递归参数向下传递。
int lp=leftP,rp=rightP;
循环查找,在左指针小于右指针的情况下,因为循环中左右指针的值会不断增减,所以这里的判读是必须的。
根据指针循环查找(先用右指针向左查找小于基准的元素,换到坑标志的元素中
while(lp<rp){
if(a[rp]<X){
a[lp]=a[rp];
// rp位置为新的坑位
// 跳出while循环
break;
}
// 右指针左移
rp--;
}
(然后,用左指针查找大于基准的元素
while(lp<rp){
if(a[lp]>X){
a[rp]=a[lp];
// 此时lp位置为新的坑位
break;
}
// 左指针右移
lp++;
}
前后两次的指针查找,我们可以查找到两个元素。一个大于基准,一个小于基准。
为了循环查找,把大于基准的放基准右边,小于基准的放基准左边,还需要循环。
while(lp<rp){
while(lp<rp){
if(a[rp]<X){
a[lp]=a[rp];
// 跳出while循环
break;
}
// 右指针左移
rp--;
}
while(lp<rp){
if(a[lp]>X){
a[rp]=a[lp];
break;
}
// 左指针右移
lp++;
}
}
填坑
此时lp=rp
左右指针相等。
// 填坑
a[lp]=X;
原数组:1,2,3,6,5,4,9,8,7,0
基准为1
第一次递归结果:0 1 3 6 5 4 9 8 7 2
此时,数组基本有序。
然后进行递归,将基准加1到数组最右索引位置的数组进行递归,传入递归函数
quickSort(a,lp+1,rightP);
同理,基准减1到数组最左索引位置的数组进行递归。
quickSort(a,leftP,rp-1);
递归则需要设定,递归终止条件。
if(leftP>=rightP){
return;
}
递归终止条件,递归进行条件的相反条件。
全部代码如下:
C++
#include <iostream>
using namespace std;
//快速排序
/**
双指针与基准选择
以及挖坑法
*/
//递归进行
void quickSort(int a[],int leftP,int rightP){
if(leftP>=rightP){
return;
}
// 基准为左边第一位元素
int X=a[leftP];
// 先由,右指针由后往前寻找小于基准的数
// 再由,左指针由前往后寻找大于基准的数
int lp=leftP,rp=rightP;
while(lp<rp){
while(lp<rp){
if(a[rp]<X){
a[lp]=a[rp];
// 跳出while循环
break;
}
// 右指针左移
rp--;
}
while(lp<rp){
if(a[lp]>X){
a[rp]=a[lp];
break;
}
// 左指针右移
lp++;
}
}
// 填坑
a[lp]=X;
// 递归
// quickSort(a,leftP,rp-1);
quickSort(a,lp+1,rightP);
}
int main(){
int a[]={1,2,3,6,5,4,9,8,7,0};
int len=sizeof(a)/sizeof(a[0]);
quickSort(a,0,len-1);
for (int i=0;i<len;i++){
cout << a[i] << " " ;
}
return 0;
}
Python
# -*- coding: utf-8 -*-
# 快速排序
# 基准
# 左右指针
# 递归思想:递归终止条件
def quick(li, left, right):
if left >= right:
return
# 基准
x = li[left]
lp = left
rp = right
# 循环填坑挖坑
while lp < rp:
while lp < rp:
if li[rp] < x:
li[lp] = li[rp]
break
rp -= 1
while lp < rp:
if li[lp] > x:
li[rp] = li[lp]
break
lp += 1
# 填坑
# 此时 lp=rp
li[lp] = x
quick(li, left, lp - 1)
quick(li, lp + 1, right)
if __name__ == '__main__':
li = [1, 2, 3, 6, 5, 4, 9, 8, 7, 0]
quick(li, 0, len(li) - 1)
print(li)