快速排序

快速排序的基本思想:通过一趟排序将待排记录分隔成独立的两部分,其中一部分记录的关键字均比另一部分的关键字小,则可分别对这两部分记录继续进行排序,以达到整个序列有序。

算法描述

快速排序使用分治法来把一个串(list)分为两个子串(sub-lists)。具体算法描述如下:

  • 从数列中挑出一个元素,称为 “基准”(pivot);
  • 重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准值大的摆在基准的后面(相同的数可以到任一边)。在这个分区退出之后,该基准就处于数列的中间位置。这个称为分区(partition)操作;
  • 递归地(recursive)把小于基准值元素的子数列和大于基准值元素的子数列排序。

Partition过程:

给定一个数组arr,和一个整数num。请把小于等于num的数放在数组的左边,大于num的数放在数组的右边。

要求额外空间复杂度O(1),时间复杂度O(N)

这里的num是数组最右边的数字

    public int partition(int[] arr, int left, int right) {
        int num = arr[right];
        int begin = left;
        int end = right;
        while (begin < end) {
            while (begin < end && arr[begin] <= num) {
                begin++;
            }
            while (begin < end && arr[end] >= num) {
                end--;
            }
            swap(arr, begin, end);
        }
        swap(arr, begin, right);
        return begin;
    }

但是如果很多相等的数字,这种方法就不是很好

下面这个方式,是将等于num的数字放在中间,小于num的放在左边,大于Num的放在右边

   // arr[L...R] 玩荷兰国旗问题的划分,以arr[R]做划分值
    //  <arr[R]  ==arr[R]  > arr[R]
    public int[] netherlandsFlag(int[] arr, int left, int right) {
        if (left > right) {
            return new int[]{-1, -1};
        }
        if (left == right) {
            return  new int[]{left, right};
        }
        int less = left - 1;
        int more = right;
        int index = left;
        while (index < more) {
            if (arr[index] == arr[right]) {
                index++;
            } else if (arr[index] < arr[right]) {
                swap(arr, index++, ++less);
            } else {
                swap(arr, index, --more);
            }

        }
        swap(arr, more, right);
        return new int[]{less + 1, more};
    }

快排1.0版本:

package com.zy.base.class003;

import java.util.Arrays;

public class Code03_PartitionAndQuickSort {
    public static void main(String[] args) {
        int[] arr = {3, 1, 3, 2, 10, 8, 9, 6, 8, 6};
        new Code03_PartitionAndQuickSort().quickSort1(arr);
        System.out.println(Arrays.toString(arr));
    }

    public int partition(int[] arr, int left, int right) {
        int num = arr[right];
        int begin = left;
        int end = right;
        while (begin < end) {
            while (begin < end && arr[begin] <= num) {
                begin++;
            }
            while (begin < end && arr[end] >= num) {
                end--;
            }
            swap(arr, begin, end);
        }
        swap(arr, begin, right);
        return begin;
    }

    private void swap(int[] arr, int left, int right) {
        int tmp = arr[left];
        arr[left] =arr[right];
        arr[right] = tmp;
    }

    // 快排递归版本
    public void quickSort1(int[] arr) {
        if (arr == null || arr.length < 2) {
            return;
        }
        process1(arr, 0, arr.length - 1);
    }

    private void process1(int[] arr, int left, int right) {
        if (left >= right) {
            return;
        }
        int partition = partition(arr, left, right);
        process1(arr, left, partition - 1);
        process1(arr, partition + 1, right);
    }
}

快速排序2.0版本

package com.zy.base.class003;

import java.util.Arrays;

public class Code03_PartitionAndQuickSort {
    public static void main(String[] args) {
        int[] arr = {3, 1, 3, 2, 10, 8, 9, 6, 8, 6};
//        int partition = new Code03_PartitionAndQuickSort().partition(arr, 0, arr.length - 1);
//        System.out.println(partition);
//        new Code03_PartitionAndQuickSort().netherlandsFlag(arr, 0, arr.length - 1);
        new Code03_PartitionAndQuickSort().quickSort2(arr);
        System.out.println(Arrays.toString(arr));

    }


    // arr[L...R] 玩荷兰国旗问题的划分,以arr[R]做划分值
    //  <arr[R]  ==arr[R]  > arr[R]
    public int[] netherlandsFlag(int[] arr, int left, int right) {
        if (left > right) {
            return new int[]{-1, -1};
        }
        if (left == right) {
            return  new int[]{left, right};
        }
        int less = left - 1;
        int more = right;
        int index = left;
        while (index < more) {
            if (arr[index] == arr[right]) {
                index++;
            } else if (arr[index] < arr[right]) {
                swap(arr, index++, ++less);
            } else {
                swap(arr, index, --more);
            }

        }
        swap(arr, more, right);
        return new int[]{less + 1, more};
    }

    private void swap(int[] arr, int left, int right) {
        int tmp = arr[left];
        arr[left] =arr[right];
        arr[right] = tmp;
    }



    // 快排递归版本
    public void quickSort2(int[] arr) {
        if (arr == null || arr.length < 2) {
            return;
        }
        process2(arr, 0, arr.length - 1);
    }

    private void process2(int[] arr, int left, int right) {
        if (left >= right) {
            return;
        }
        int[] ints = netherlandsFlag(arr, left, right);
        process2(arr, left, ints[0] - 1);
        process2(arr, ints[1] + 1, right);

    }
}

快速排序3.0

package com.zy.base.class003;

import java.util.Arrays;

public class Code03_PartitionAndQuickSort {
    public static void main(String[] args) {
        int[] arr = {3, 1, 3, 2, 10, 8, 9, 6, 8, 6};
//        int partition = new Code03_PartitionAndQuickSort().partition(arr, 0, arr.length - 1);
//        System.out.println(partition);
//        new Code03_PartitionAndQuickSort().netherlandsFlag(arr, 0, arr.length - 1);
        new Code03_PartitionAndQuickSort().quickSort3(arr);
        System.out.println(Arrays.toString(arr));


    }


    // arr[L...R] 玩荷兰国旗问题的划分,以arr[R]做划分值
    //  <arr[R]  ==arr[R]  > arr[R]
    public int[] netherlandsFlag(int[] arr, int left, int right) {
        if (left > right) {
            return new int[]{-1, -1};
        }
        if (left == right) {
            return  new int[]{left, right};
        }
        int less = left - 1;
        int more = right;
        int index = left;
        while (index < more) {
            if (arr[index] == arr[right]) {
                index++;
            } else if (arr[index] < arr[right]) {
                swap(arr, index++, ++less);
            } else {
                swap(arr, index, --more);
            }

        }
        swap(arr, more, right);
        return new int[]{less + 1, more};
    }

    private void swap(int[] arr, int left, int right) {
        int tmp = arr[left];
        arr[left] =arr[right];
        arr[right] = tmp;
    }


    public void quickSort3(int[] arr) {
        if (arr == null || arr.length < 2) {
            return;
        }
        process3(arr, 0, arr.length - 1);
    }

    private void process3(int[] arr, int start, int end) {
        if (start >= end) {
            return;
        }
        swap(arr, start + (int) Math.random() * (end - start + 1), end);
        int[] ints = netherlandsFlag(arr, start, end);
        process3(arr, start, ints[0] - 1);
        process3(arr, ints[0] + 1, end);
    }
}

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值