java面试常问之快速排序

一、快速排序介绍

1、优点

快速排序是一种原地排序算法,它只需要一个很小的栈空间来保存递归调用信息,而不需要额外的存储空间来存储待排序的元素。

2、时间复杂度

快速排序的时间复杂度在最理想的情况下是 O(n log n),其中 n 是待排序数组的元素数量。这发生在每次分区操作都能将数组划分为几乎相等的两部分时。

在最坏的情况下,当待排序的数组已经是有序的,或者输入数组的元素几乎相同,那么快速排序的时间复杂度可能会退化到 O(n^2)。这是因为分区操作可能每次只移动一个元素,导致算法需要进行多次递归调用,从而产生大量的比较和交换操作。

3、提高鲁棒性的手段

为了避免最坏情况的发生,可以采取一些优化措施,如随机化选择基准元素(pivot),或者使用三数取中等方法来选择基准元素,以提高算法的鲁棒性。

二、快速排序基本思想

快速排序的原理主要基于“分而治之”的思想。具体步骤如下:

  1. 首先,从待排序的数组中选取一个基准元素(pivot),通常选择第一个元素或者最后一个元素,或者通过某种方式随机选取一个元素。
  2. 接下来,通过一趟排序将待排序列分成两部分,其中一部分所有元素都比基准元素小,另一部分所有元素都比基准元素大(或者等于基准元素),此时基准元素在其排好序后的正确位置。
  3. 然后,递归地对这两部分数据进行快速排序。也就是说,对左边的子序列和右边的子序列分别重复执行步骤1和步骤2,直到整个序列有序。

三、快速排序java程序

package com.xmx.testDemo;

public class quikSort {
    public static void main(String[] args){
        int[] arr = {1,2,4,56,56,1,3,123,14,3,1,243,134,32,41};
        quick1(arr,0,arr.length  - 1);
        for(int num : arr){
            System.out.print(num + " ");
        }
    }

    public static void quick1(int[] arr,int left,int right){
        if(left < right){
            //获取基准元素索引位置
            int partitionIndex = getPartition(arr,left,right);
            quick1(arr,left,partitionIndex - 1);
            quick1(arr,partitionIndex  + 1,right);
        }
    }

    //手写快排
    public static int getPartition(int[] arr,int left,int right){
        int privot = arr[left];
        int i = left;
        int j = right;

        //开始遍历
        while(i < j){
            while(i < j && arr[j] >= privot){
                j--;
            }
            //此时左右指针没有相遇
            if(i < j){
                arr[i] = arr[j];
                i++;
            }

            while(i < j && arr[i] < privot){
                i++;
            }
            //此时左右指针没有相遇
            if(i < j){
                arr[j] = arr[i];
                j--;
            }

        }
        arr[j] = privot;
        return j;
    }
}

四、随机化选取和使用三数取中法

package com.xmx.testDemo;

import java.util.Random;

public class quikSort {
    public static void main(String[] args){
        int[] arr = {1,2,4,56,56,1,3,123,14,3,1,243,134,32,41};
        System.out.print("排序前:");
        for(int num : arr){
            System.out.print(num + " ");
        }
        quick1(arr,0,arr.length  - 1);

        System.out.print("\n排序后:");
        for(int num : arr){
            System.out.print(num + " ");
        }
    }

    public static void quick1(int[] arr,int left,int right){
        if(left < right){
            //获取基准元素索引位置
            int partitionIndex = getPartition(arr,left,right);
            quick1(arr,left,partitionIndex - 1);
            quick1(arr,partitionIndex  + 1,right);
        }
    }

    //手写快排
    public static int getPartition(int[] arr,int left,int right){

        // 随机化选取基准元素索引
        int randomPivotIndex = getRandomPivotIndex(left, right);
        // 将基准元素交换到最左边
        swap(arr, left, randomPivotIndex);

        int privot = arr[left];
        int i = left;
        int j = right;

        //开始遍历
        while(i < j){
            while(i < j && arr[j] >= privot){
                j--;
            }
            //此时左右指针没有相遇
            if(i < j){
                arr[i] = arr[j];
                i++;
            }

            while(i < j && arr[i] < privot){
                i++;
            }
            //此时左右指针没有相遇
            if(i < j){
                arr[j] = arr[i];
                j--;
            }

        }
        arr[j] = privot;
        return j;
    }

    // 随机化选取基准元素索引
    private static int getRandomPivotIndex(int left, int right) {
        Random rand = new Random();
        //确保生成的数字在[left,right - left + 1)之间,不包含右边界值。
        return left + rand.nextInt(right - left + 1);  
    }
    // 交换数组中两个元素的位置
    private static void swap(int[] arr, int i, int j) {
        int temp = arr[i];
        arr[i] = arr[j];
        arr[j] = temp;
    }
}
public class QuickSortMedianOfThree {  
    public static void quickSort(int[] arr, int low, int high) {  
        if (low < high) {  
            int pivotIndex = partition(arr, low, high);  
            quickSort(arr, low, pivotIndex - 1);  
            quickSort(arr, pivotIndex + 1, high);  
        }  
    }  
  
    private static int partition(int[] arr, int low, int high) {  
        int mid = (low + high) / 2;  
        // 三数取中法选择基准元素  
        if (arr[mid] < arr[low]) {  
            swap(arr, mid, low);  
        }  
        if (arr[high] < arr[low]) {  
            swap(arr, high, low);  
        }  
        if (arr[mid] < arr[high]) {  
            swap(arr, mid, high);  
        }  
        // 此时arr[high]已经是三个数中的中位数,将它作为基准元素  
        swap(arr, high, high - 1); // 将基准元素放到倒数第二个位置  
        int pivot = arr[high - 1];  
        int i = low;  
        for (int j = low; j < high - 1; j++) {  
            if (arr[j] < pivot) {  
                swap(arr, i, j);  
                i++;  
            }  
        }  
        swap(arr, i, high - 1); // 将基准元素放到正确的位置  
        return i;  
    }  
  
    private static void swap(int[] arr, int i, int j) {  
        int temp = arr[i];  
        arr[i] = arr[j];  
        arr[j] = temp;  
    }  
  
    public static void main(String[] args) {  
        int[] arr = {9, 7, 5, 11, 12, 2, 14, 3, 10, 6};  
        quickSort(arr, 0, arr.length - 1);  
        for (int num : arr) {  
            System.out.print(num + " ");  
        }  
    }  
}

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

数学控制原理

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值