快速排序

快速排序冒泡排序都属于交换排序,但不同于冒泡排序的是冒泡排序每一轮都只排出一个元素,而快速排序则在每一轮选定一个基准元素,然后将比它大的移到一边,小的移到另一边,拆解成两部分,这种方法叫做分治法。这样做的好处就是大大降低的时间复杂度,冒泡排序时间复杂度是O(n^2),而快速排序的平均时间复杂度是O(nlogn)

但是这种简单的快速排序在遇到8,7,6,5,4,3这种本来逆序列的情况下就会出现时间复杂度为O(n^2),你可以不取第一个值8为基准元素,但是这存在概率问题,有很小的机率会取到想要的中间值,所以最坏的情况会出现时间复杂度为O(n^2),平均时间复杂度是O(nlogn),怎么把小于和大于povit的值分到两部分呢,下面有两种方法可以选择:

  • 填坑法

首先选定一个元素为基准元素pivot,然后记住位置Index,这个位置相当于一个坑位,然后设置两个指针left和right,指向最左位置和最右位置。然后从right开始进行比较,如果比pivot大,则指针左移一下,若小于pivot则将right与index位置的povit交换,然后停止进行left指针比较,若值比povit小则left右移一下,若比povit大则将left与index位置的povit交换然后开始切换到right指针。最后left与right和index指针重合的时候将povit的值填入坑内。

package QuickSort;

public class QuickSort1 {
    public static void quicksort1(int[] arr,int startIndex,int endIndex){
        //递归结束条件:startIndex大于或者等于endIndex
        if(startIndex>=endIndex){
            return;
        }
        //得到基准元素位置
        int pivotIndex=partition(arr, startIndex, endIndex);
        //根据基准元素来分成两部分来递归进行排序
        quicksort1(arr,startIndex,pivotIndex-1);
        quicksort1(arr,pivotIndex+1,endIndex);

    }
    private static int partition(int[] arr, int startIndex, int endIndex) {
        //取第一个元素为基准元素
        int pivot=arr[startIndex];
        int left=startIndex;
        int right=endIndex;
        //填充元素的坑的位置。初始位置是pivot,也就是初始位置
        int index=startIndex;
        //当left指针和right指针重合循环结束
        while (right>=left){
            while (right>=left){
                if(arr[right]<pivot){
                    arr[left]=arr[right];
                    index=right;
                    left++;
                    break;
                }
                right--;
            }
            while (right>=left){
                if(arr[left]>pivot){
                    arr[right]=arr[left];
                    index=left;
                    right--;
                    break;
                }
                left++;
            }
        }
        arr[index]=pivot;
        return  index;


    }

    public static void main(String[] args) {
        int[] arr=new int[]{5,3,2,6,4,8,7,1,0};
        quicksort1(arr,0,arr.length-1);
        for (int i = 0; i <arr.length; i++) {
            System.out.print(arr[i]+",");
        }
    }


    }
  • 指针交换法

选定元素povit,然后设置left和right指针指向数列的最左和最右,从right开始比较,当right值比povit大时,指针左移一下,当比povit小时right停止移动转向left指针,当left指针的值比povit小或相等时left指针右移一下,当比povit大时,交换此时的left与right的值,然后继续进行right的比较。当left和right相等时,把povit的值与left和right的值交换。

package QuickSort;

public class QuickSort2 {
    public static void quicksort2(int[] arr,int startIndex,int endIndex){
        //递归结束条件:startIndex大于或者等于endIndex
        if(startIndex>=endIndex){
            return;
        }
        //得到基准元素位置
        int pivotIndex=partition(arr, startIndex, endIndex);
        quicksort2(arr,startIndex,pivotIndex-1);
        quicksort2(arr,pivotIndex+1,endIndex);

    }
    private static int partition(int[] arrs, int startIndex, int endIndex) {
        //取第一个元素为基准元素
        int pivot=arrs[startIndex];
        int left=startIndex;
        int right=endIndex;
        //当left指针和right指针重合循环结束
        while (right!=left){
            while (left<right&&arrs[right]>pivot){
                right--;
            }
            while (left<right&&arrs[left]<=pivot){
                left++;
            }
            if (left<right){
                int p=arrs[left];
                arrs[left]=arrs[right];
                arrs[right]=p;
            }

        }
        //left和right重合后,基准元素和重合点交换
        int p=arrs[left];
        arrs[left]=arrs[startIndex];
        arrs[startIndex]=p;
        //返回基准元素的位置
        return  left;


    }

    public static void main(String[] args) {
        int[] arr=new int[]{1,3,2,6,4,8,7,0};
        quicksort2(arr,0,arr.length-1);
        for (int i = 0; i <arr.length; i++) {
            System.out.print(arr[i]+",");
        }
    }


    }

这里采用递归的方法实现分治的思想,当然也可以用栈的方式来代替,方法一层一层的调用本身就相当于一个函数栈,可以把其放入栈内操作一样的道理。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值