排序算法(四):快速排序

  • 快速排序由C. A. R.
    Hoare在1962年提出。
    它的基本思想是:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列

  • 时间复杂度: 最坏 O(N ^ 2)(如果数组是逆序的) 平均水平 O(NlogN)
  • 空间复杂度: O(N) 递归. 最坏情况下要递归 N层
    稳定性: 不稳定排序

  • 以最左边为基准值

package com.company;

public class QuickSort {
    public static void main(String[] args) {
        int array[] = {1, 0, 6, 12, 7, 9, 3, 4, 5, 10, 8};
        quickSort(array, 0, array.length - 1);
        for (int i: array) {
            System.out.print(i + " ");
        }
    }

    /**
     * 快速排序,递归实现
     * 写代码要注意边界问题
     * @param array:数组最左下标,0
     * @param start:数组最右下标,length - 1
     * @param end
     */
    public static void quickSort(int array[], int start, int end){
        int pivot = array[start];// 关键值或基准值
        int left = start;
        int right = end;
        if(left >= right){
            return;
        }
        while(left != right){
            // 向左走,找比pivot小的数(必须right先走,因选的基准值为最左边的数)
            while(left < right && array[right] >= pivot){
                right--;
            }
            // 向右走,找到比pivot大的数
            while(left < right && array[left] <= pivot){
                left++;
            }
            // 没有相遇,但找到了,交换两数
            if(left < right){
                int tmp = array[left];
                array[left] = array[right];
                array[right] = tmp;
            }
        }
        // 退出while循环或没进去,表示left == right
        array[start] = array[left];
        array[left] = pivot;

        // 子问题,递归解决左边与右边
        quickSort(array, start, left -1);
        quickSort(array, left + 1, end);
    }
}

这里写图片描述


  • 以最右作为基准值

package com.company;

public class QuickSortRight {
    public static void QuickSort(int num[], int start, int end){
        int pivot = num[end];   // 以最右边的数字为基准值
        int left = start;
        int right = end;

        if(left >= right){
            return;
        }

        while(left != right){
            //左边先走,找比pivot大的数(因为升序排序)
            while(left < right && num[left] <= pivot){
                left++;
            }
            //右边再走,找比pivot小的数
            while(left < right && num[right] >= pivot){
                right--;
            }
            // 此时,左右都找到了,但没有相遇,交换两数
            if(left < right){
                int tmp = num[left];
                num[left] = num[right];
                num[right] = tmp;
            }
        }

        // 不满足while循环时,left与right相遇,将基准值与相遇的数进行替换
        num[end] = num[left];
        num[left] = pivot;

        // 子问题分别处理相遇下标左右两边的数
        QuickSort(num, start, left - 1);
        QuickSort(num, left + 1, end);
    }

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

这里写图片描述


  • 非递归实现

package com.company;

import java.util.Stack;

public class QuickSortByLoop {
    public static void main(String[] args) {
        int arr[] = {9, 5, 11, 3, 4, 6, 7, 7, 11};
        _quickSort(arr);
        for (int i : arr) {
            System.out.print(i + " ");
        }
    }

    /**
     * 一次分割
     * @param arr
     * @param start 开始下标
     * @param end   结束下标
     * @return
     */
    public static int partition(int arr[], int start, int end) {
        int pivot = arr[start]; // 基准值
        int left = start;
        int right = end;

        while (left !=  right) {
            while (left < right && arr[right] >= pivot) {
                right--;
            }
            while (left < right && arr[left] <= pivot) {
                left++;
            }
            if (left < right) {
                int tmp = arr[left];
                arr[left] = arr[right];
                arr[right] = tmp;
            }
        }
        // 退出while循环
        arr[start] = arr[left];
        arr[left] = pivot;

        return left;
    }

    /**
     * 用栈实现:方法1
     * @param arr
     */
    public static void quickSort(int[] arr) {
        int start = 0;
        int end = arr.length - 1;

        if (start < end) {
            // 定义一个栈
            Stack<Integer> stack = new Stack<>();
            int mid = partition(arr, start, end);

            if (start < mid - 1) {
                stack.push(start);
                stack.push(mid - 1);
            }
            if (mid + 1 < end) {
                stack.push(mid + 1);
                stack.push(end);
            }

            while (!stack.isEmpty()) {
                int q = stack.peek();
                stack.pop();
                int p = stack.peek();
                stack.pop();

                mid = partition(arr, p, q);

                if (p < mid - 1) {
                    stack.push(p);
                    stack.push(mid - 1);
                }
                if (mid + 1 < q) {
                    stack.push(mid + 1);
                    stack.push(q);
                }
            }
        }
    }

    /**
     *用栈实现:方法2
     * @param arr
     */
    public static void _quickSort(int[] arr){
        int left = 0;
        int right = arr.length - 1;
        if(left >= right)
            return;
        Stack<Integer> stack = new Stack<>();
        stack.push(left);
        stack.push(right);
        while(!stack.isEmpty()){
            int q = stack.peek();
            stack.pop();
            int p = stack.peek();
            stack.pop();

            int mid = partition(arr, p, q);

            if(p < mid - 1){
                stack.push(p);
                stack.push(mid - 1);
            }
            if(mid + 1 < q){
                stack.push(mid + 1);
                stack.push(q);
            }
        }
    }

}


这里写图片描述



猜你喜欢

转载自blog.csdn.net/qq_39026129/article/details/81592113