码迷,mamicode.com
首页 > 编程语言 > 详细

八大排序之快速排序

时间:2019-09-02 19:14:46      阅读:90      评论:0      收藏:0      [点我收藏+]

标签:代码   部分   简单   排序   思想   记录   计算   while   中间   

1.简述

快速排序是一种排序执行效率很高的排序算法,它利用分治法来对待排序序列进行分治排序,它的思想主要是通过一趟排序将待排记录分隔成独立的两部分,其中的一部分比关键字小,后面一部分比关键字大,然后再对这前后的两部分分别采用这种方式进行排序,通过递归的运算最终达到整个序列有序,下面我们简单进行阐述。

2.快排思路

我们从一个数组来逐步逐步说明快速排序的方法和思路。

<1> 假设我们对数组{7, 1, 3, 5, 13, 9, 3, 6, 11}进行快速排序。
<2> 首先在这个序列中找一个数作为基准数,为了方便可以取第一个数。
<3> 遍历数组,将小于基准数的放置于基准数左边,大于基准数的放置于基准数右边。
<4> 此时得到类似于这种排序的数组{3, 1, 3, 5, 6, 7, 9, 13, 11}。
<5> 在初始状态下7是第一个位置,现在需要把7挪到中间的某个位置k,也即k位置是两边数的分界点。
<6> 那如何做到把小于和大于基准数7的值分别放置于两边呢,我们采用双指针法,从数组的两端分别进行比对。
<7> 先从最右位置往左开始找直到找到一个小于基准数的值,记录下该值的位置(记作 i)。
<8> 再从最左位置往右找直到找到一个大于基准数的值,记录下该值的位置(记作 j)。
<9> 如果位置i<j,则交换i和j两个位置上的值,然后继续从(j-1)的位置往前和(i+1)的位置往后重复上面比对基准数然后交换的步骤。
<10> 如果执行到i==j,表示本次比对已经结束,将最后i的位置的值与基准数做交换,此时基准数就找到了临界点的位置k,位置k两边的数组都比当前位置k上的基准值或都更小或都更大。
<11> 上一次的基准值7已经把数组分为了两半,基准值7算是已归位(找到排序后的位置)。
<12> 通过相同的排序思想,分别对7两边的数组进行快速排序,左边对[left, k-1]子数组排序,右边则是[k+1, right]子数组排序。
<13> 利用递归算法,对分治后的子数组进行排序。

快速排序之所以比较快,是因为相比冒泡排序,每次的交换都是跳跃式的,每次设置一个基准值,将小于基准值的都交换到左边,大于基准值的都交换到右边,这样不会像冒泡一样每次都只交换相邻的两个数,因此比较和交换的此数都变少了,速度自然更高。当然,也有可能出现最坏的情况,就是仍可能相邻的两个数进行交换。

快速排序基于分治思想,它的时间平均复杂度很容易计算得到为O(NlogN)。

3.基数选取

3.1 三数取中

public static void dealPivot(int[] arr, int left, int right) {
        int mid = (left + right) / 2;

        if (arr[left] > arr[mid]) {
            swap(arr, left, mid);
        }

        if (arr[left] > arr[right]) {
            swap(arr, left, right);
        }

        if (arr[right] < arr[mid]) {
            swap(arr, right, mid);
        }

        swap(arr, right - 1, mid);
    }

3.代码实现

package com.buxiaoxia.business.sort;

public class QuickSort {

    public static void dealPivot(int[] arr, int left, int right) {
        int mid = (left + right) / 2;

        if (arr[left] > arr[mid]) {
            swap(arr, left, mid);
        }

        if (arr[left] > arr[right]) {
            swap(arr, left, right);
        }

        if (arr[right] < arr[mid]) {
            swap(arr, right, mid);
        }

        swap(arr, right - 1, mid);
    }

    public static void swap(int[] arr, int a, int b) {
        int tmp = arr[a];
        arr[a] = arr[b];
        arr[b] = tmp;
    }

    public static void quickSort(int[] arr, int left, int right) {
        if (left < right) {
            // 获取枢纽值,并将其放在当前待处理序列末尾
            dealPivot(arr, left, right);
            // 枢纽值被放在序列末尾
            int pivot = right - 1;
            // 左指针
            int i = left;
            // 右指针
            int j = right - 1;
            while (true) {
                while (arr[++i] < arr[pivot]) {
                }
                while (j > left && arr[--j] > arr[pivot]) {
                }
                if (i < j) {
                    swap(arr, i, j);
                } else {
                    break;
                }
            }
            if (i < right) {
                swap(arr, i, right - 1);
            }
            quickSort(arr, left, i - 1);
            quickSort(arr, i + 1, right);
        }
    }

}

八大排序之快速排序

标签:代码   部分   简单   排序   思想   记录   计算   while   中间   

原文地址:https://www.cnblogs.com/kevliudm/p/11445899.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!