实现快速排序算法的另一种思路

一、快速排序算法

快速排序的基本思想如下:

  1. 从数组中取出一个数作为中轴数(pivot)
  2. 划分数组:将比这个数大的数放到它的右边,小于或等于它的数放到它的左边
  3. 再对左右区间重复上述步骤,直到各区间只有一个数在这里插入图片描述
    本篇文章实现快速排序算法的主要思路是:
    1) 定义两个前向指针i,j,i记录小于中轴数的分区,通过指针j遍历数组,并将每个j位置的元素和pivot(中轴数)进行比较,arr[j] 小于 pivot 时,将arr[j]和arr[i] 交换位置,否则j直接后移继续下一个元素的遍历;
    2) 最后将pivot和i-1位置(i前面的元素都小于中轴数)的数据交换;
    3) 递归。
二、实例排序分析

样本数据:{5,8,4,3,2,5,7,9}

  • 中轴数pivot: 一般取待排序序列的第一个(当然这个数可以选一个能让数组均匀分布的数)
  • 目标: 交换后, 中轴数左边的数要全部小于中轴数, 其右边的数要全部大于等于中轴数
    在这里插入图片描述
    步骤如下:
  • 定义两个指针 i,j,从中轴数后一位开始,即start+1的位置;
  • 通过j对数组进行循环遍历,并每次和中轴数比较,小于中轴数则将arr[j] 和arr[i]数据交换,同时i++,指向后一位置;大于中轴数则继续下一个元素比较;
  • 如第一次遍历比较后(8>5),只对j后移在这里插入图片描述
    第二次比较后(4<5),4和8交换位置,同时i++,j++:
    在这里插入图片描述
    第一轮循环遍历后的结果如下:
    在这里插入图片描述
    此时将start位置的pivot和i-1位置的数据交换:
    在这里插入图片描述
  • 至此,以中轴数分为3部分,左边的都比其小,右边的都比其大。

对于左右两部分数据再通过递归分别进行快速排序。

三、算法实现

实现代码如下:

/**
 * 两个先后指针实现快排
 */
public class QuickSort {
   
    public void sort(int[] arr) {
        if(arr == null || arr.length <= 1) {
            return;
        }
        sortHelper(arr, 0, arr.length-1);
    }

    private void sortHelper(int[] arr, int start, int end) {
        if(start >= end){
            return;
        }
        // 分治
        int middle = partition(arr, start, end);
        // 左右部分进行递归
        sortHelper(arr, start, middle - 1);
        sortHelper(arr, middle+1, end);
    }

    private int partition(int[] arr, int start, int end) {
        // 选一个中轴数 pivot, 一般选第一个数即可
        int pivot = arr[start];

        int i = start + 1; // 从第二个数开始循环比较
        for(int j=start+1; j <= end; j++){
            if(arr[j] < pivot){
                swap(arr, i, j);
                i++;
            }
            printArray(arr);
        }

        // 第i 个数为大于pivot 的数, 将pivot 和i 的前一位置交换
        swap(arr, start, i-1);

        // 返回pivot位置
        return i-1;
    }

    private void swap(int[] arr, int i, int j) {
        int temp = arr[i];
        arr[i] = arr[j];
        arr[j] = temp;
    }

    /**
	 * 数组打印
	 * @param arr
	 */
	public static void printArray(int arr[])  { 
        int n = arr.length; 
        for (int i=0; i<n; ++i) 
            System.out.print(arr[i] + " "); 
        System.out.println(); 
    } 
    
    public static void main(String[] args) {
        int[] arrayToSort = {5,8,4,3,2,5,7,9};
        printArray(arrayToSort);
        int[] arrayClone = Arrays.copyOf(arrayToSort, arrayToSort.length);
     
        Sorter sorter = new QuickSort();
        sorter.sort(arrayToSort);
        printArray(arrayToSort);
        
         // jdk 排序
        Arrays.sort(arrayClone);
        System.out.println("jdk Arrays.sort排序结果:");
        printArray(arrayClone);
    }

}

运行结果:

5 8 4 3 2 5 7 9 
5 8 4 3 2 5 7 9 
5 4 8 3 2 5 7 9 
5 4 3 8 2 5 7 9 
5 4 3 2 8 5 7 9 
5 4 3 2 8 5 7 9 
5 4 3 2 8 5 7 9 
5 4 3 2 8 5 7 9 
2 4 3 5 8 5 7 9 
2 4 3 5 8 5 7 9 
2 4 3 5 8 5 7 9 
2 3 4 5 8 5 7 9 
2 3 4 5 8 5 7 9 
2 3 4 5 8 5 7 9 
2 3 4 5 7 5 8 9 
排序结果:
2 3 4 5 5 7 8 9 
jdk 排序结果:
2 3 4 5 5 7 8 9 

由于快排需要交换元素顺序,不保证相同元素的起始先后顺序,所以快排是不稳定排序。

注: 快速排序的最好的情况(每次数据划分得很均匀)时间复杂度为O(nlogn),最坏的情况(需排序的数据为正序或逆序排列时)复杂度为O(n^2)。



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值