快速排序(Quick Sort)算法和冒泡排序算法类似,都是基于交换排序思想的。快速排序算法对冒泡排序算法进行了改进,从而具有了更高的执行效率。
快速排序算法通过多次比较和交换来实现排序,排序流程如下:
1. 从待排序的数组中选一个基准值(通常取数组中间位置的值或者第一个值),通过该基准值将数组分成左右两部分。其中大于等于基准值的数据在右部分,小于等于基准值的数据为左部分。
2. 左右两部分的数据右可以独立选取基准值并排序,参照1,通过递归排好左侧数据,然后再递归排好右侧数据。
一句话理解快速排序,取数组中间位置的值作为基准,将输入集分为两半,左右部分不断递归,排序完成。
以一组实验数据来加深理解:
每一行带颜色的部分为分区结果,红色代表左半部分(为左侧递归的输入,并且下一行的基准为该部分中间位置的值),绿色代表右半部分(为左侧递归的输入,并且下一行的基准为该部分中间位置的值)
排序前的数组为: 122 141 164 149 198 166 178 106
以149第一次分区: 122 141 106 149 198 166 178 164 ,基准149为上一行数据中间位置的值
对左区(122 141 106 149 )进行递归
以141为基准左侧递归: 122 106 141 149 198 166 178 164 ,基准141为上一行左区数据中间位置的值以122为基准左侧递归: 106 122 141 149 198 166 178 164 ,基准122为上一行左区数据中间位置的值
以141为基准右侧递归:106 122 141 149 198 166 178 164 ,基准141为上一行右区数据中间位置的值
左部分排列完成
对右区(198 166 178 164 )进行递归
以164为基准左侧递归:106 122 141 149 164 166 178 198
以178为基准右侧递归:106 122 141 149 164 166 178 198
右部分排列完成
排序后的数组为: 106 122 141 149 164 166 178 198
下面为自己写快速排序算法
详细实现见以下注解,如需完整代码,请直接跳过这一段
<pre name="code" class="java">void quickSort(int[] arr, int left, int right) // 快速排序算法
{
int f, t;
int rtemp, ltemp;
ltemp = left;
rtemp = right;
// f = arr[(left + right) / 2]; // 分界值
f =arr[left];
// f=arr[right];
//不能使用最右侧数作为基准,因为左指针等于右指针时(下面的if语句中),默认当前值小于等于基准时,左指针++;
//只需改为当前值大于等于基准时,右指针--;此语句就可以,同理此时f不能等于最左侧
while (ltemp < rtemp) {
while (arr[ltemp] < f) { //不能取等号,当基准左边都小于等于基准时,ltemp会越过基准的索引
++ltemp;
}
while (arr[rtemp] > f) {
--rtemp;
}
//此时如果ltemp==rtemp并且当前值小于等于基准值,执行下一个if,让ltemp指针后移(当然也可以让rtemp前移,此时不能用a[left]作为基准)
if (ltemp<rtemp) { //去掉if的话偶尔会排序出错,比如138 181 150 119 118 123 113 124 166 116 167 117 141 163 130 167 191 108
t = arr[ltemp];
arr[ltemp] = arr[rtemp];
arr[rtemp] = t;
--rtemp;
++ltemp;
}
}
//下一个if保证ltemp为rtemp+1
//ltemp左侧的数据小于等于基准,rtemp右侧大于等于基准,
if (ltemp == rtemp) {
if (arr[ltemp] <= f)
ltemp++;
else
rtemp--;
}
//左右分区结束,进入递归
if (left < rtemp) {
quickSort(arr, left, ltemp - 1); // 递归调用,实现左部分排序,ltemp左侧必定是小于等于分解值,rtemp减小到left,递归结束
//
}
if (ltemp < right) {
quickSort(arr, rtemp + 1, right); // 递归调用,实现右部分排序,rtemp右侧必定是大于等于分解值,ltemp增大到right,递归结束
}
}
完整java代码:
public class test {
static final int SIZE = 18;
static void quickSort(int[] arr, int left, int right) // 快速排序算法
{
int f, t;
int rtemp, ltemp;
ltemp = left;
rtemp = right;
// f = arr[(left + right) / 2]; // 分界值
f =arr[left];
// f=arr[right];
while (ltemp < rtemp) {
while (arr[ltemp] < f) {
++ltemp;
}
while (arr[rtemp] > f) {
--rtemp;
}
if (ltemp<rtemp) {
t = arr[ltemp];
arr[ltemp] = arr[rtemp];
arr[rtemp] = t;
--rtemp;
++ltemp;
}
}
if (ltemp == rtemp) {
if (arr[ltemp] <= f)
ltemp++;
else
rtemp--;
}
if (left < rtemp) {
quickSort(arr, left, ltemp - 1); // 递归调用
}
if (ltemp < right) {
quickSort(arr, rtemp + 1, right); // 递归调用
}
}
public static void main(String[] args) {
int[] shuzu = new int[SIZE];
int i;
for (i = 0; i < SIZE; i++) {
shuzu[i] = (int) (100 + Math.random() * (100 + 1)); // 初始化数组
}
System.out.print("排序前的数组为:\n"); // 输出排序前的数组
for (i = 0; i < SIZE; i++) {
System.out.print(shuzu[i] + " ");
}
System.out.print("\n");
quickSort(shuzu, 0, SIZE - 1); // 排序操作
System.out.print("排序后的数组为:\n");
for (i = 0; i < SIZE; i++) {
System.out.print(shuzu[i] + " "); // 输出排序后的数组
}
System.out.print("\n");
}
}
欢迎指出不足或者给点建议。