递归应用->快速排序算法

简单总结:分而治之,然后递归

1.取一个基准值对所有待排序元素分区。 比基准值小的元素放左边,比基准值大的元素放右边

     基准值最好是随机选出来的,尽可能避免最坏情况,可参考《剑指Offer 数据结构与算法名企面试题精讲》(何海涛著)第12.3章节,代码虽然麻烦点,但是效率得到了保障,如果读者不理解如何对数组快速排序,也可参阅此章节。

     本例选第一个元素作为基准值,不是最优解,但是代码量少,适合笔试用。

2. 分别对左边元素 和 右边元素执行上述步骤,直到待排序元素个数<=1, 跳出递归

快速排序平均运行时间为O(nlogn),最糟情况的运行时间为O(n平方),详情可参阅《算法图解》(Aditya Bhargava著 袁国忠译)第4.3章节

package xia.test;

import java.util.Arrays;

public class Digui {
  
    public void quickSort(int[] a, int begin, int end){
        //递归的基线条件:如果待排序的数组元素只有一个或没有时(end-begin<1),不用排序,退出递归
        if(end-begin<1){
            return ;
        }
        //递归条件:数组元素>1个

        //设置基准值(取begin位置的元素值)
        int base = a[begin];

        //对数组索引为begin和end之间的区域进行分区,使小于等于基准值的元素处于基准值的左侧,大者处于基准值的右侧
        //分区开始
        //用两个指针,left和right
        int left = begin;
        int right = end;
        while (left < right){
            //1. right从end出发往左,找到第一个比基准值小的元素
            while(a[right]>base && left<right){
                right--;
            }
            //2. left从begin出发往右,找到第一个比基准值大的元素
            while(a[left]<=base && left<right){
                left++;
            }

            //3. 如果left与right没有相逢,交换left与right的元素
            if(left!=right){
                int temp = a[left];
                a[left] = a[right];
                a[right] = temp;
            }

            //4. left继续往右走,right继续往左走,重复1-4步
        }

        //如果left与right相逢,即表示begin与end区域内的元素都遍历完了,碰撞点左侧都是小于或等于基准值的元素,右侧反之。
        //此时基准值还在begin位置,应将它移到碰撞点(交换begin和left的元素)
        a[begin] = a[left];
        a[left] = base;
        //分区结束

        //递归调用本方法,对基准值左侧的数组进行排序
        quickSort(a, begin, left-1);

        //递归调用本方法,对基准值右侧的数组进行排序
        quickSort(a, left+1, end);
    }


    public static void main(String[] args) {
        Digui digui = new Digui();
        int[] b = {3,2,1,5,4,8, 6};
        digui.quickSort(b, 0, 6);
        System.out.println(Arrays.toString(b));
    }
}

运行结果:

 

posted @ 2022-02-09 16:09  Fabulous~  阅读(74)  评论(0编辑  收藏  举报