快速排序 - Java实现及时间复杂度证明思路

一. 代码实现:

package com.app.main.LeetCode.base;

import com.alibaba.fastjson.JSONObject;

/**
 * Created with IDEA
 * author:Dingsheng Huang
 * Date:2020/2/20
 * Time:下午3:39
 */
public class QuickSort {

    public static void quickSort(int[] arr, int l, int r) {
        if (l >= r) {
            return;
        }

        int pivot = arr[l];
        int i = l;
        int j = r;
        while (i < j) {
            // 从右边界开始找到第一个小于 pivot的值
            while (i < j && arr[j] > pivot) {
                j--;
            }
            if (i < j) {
                // 右边界小于 pivot的值放置于左边界
                arr[i] = arr[j];
                i++;
            }
            // 从左边界开始找到第一个大于 pivot的值
            while (i < j && arr[i] < pivot) {
                i++;
            }
            if (i < j) {
                // 左边界大于 pivot的值放置于右边界
                arr[j] = arr[i];
                j--;
            }
        }
        arr[i] = pivot;
        quickSort(arr, l, i - 1);
        quickSort(arr, i + 1, r);
    }

    public static void main(String[] args) {
        int[] testArr = new int[]{3, 1, 2, 2, 0};
        System.out.println(JSONObject.toJSONString(testArr));
        // sort
        quickSort(testArr, 0, testArr.length - 1);
        System.out.println(JSONObject.toJSONString(testArr));
    }


}

二. 时间复杂度证明思路:

快速排序的一次划分算法从两头交替搜索,直到左边界 l 和右边界 r 重合,因此其时间复杂度是O(n);

而整个快速排序算法的时间复杂度与划分的趟数有关. 

理想的情况是,每次划分所选择的中间数恰好将当前序列几乎等分,经过log2n趟划分,便可得到长度为1的子表。这样,整个算法的时间复杂度为O(nlog2n)

为什么理想情况是 log2n趟呢?

每次划分都是等分的话,正好可以得到一颗完全二叉树,而二叉树深度即趟数。

即求N 个节点的完全二叉树深度:

根据二叉树性质,具有n个结点完全二叉树的深度为

 (注:[ ]表示向下取整)

 

最坏的情况是,每次所选的中间数是当前序列中的最大或最小元素,这使得每次划分所得的子表中一个为空表,另一子表的长度为原表的长度-1。这样,长度为n的数据表的快速排序需要经过n趟划分,使得整个排序算法的时间复杂度为O(n2) .

发布了187 篇原创文章 · 获赞 26 · 访问量 4万+

猜你喜欢

转载自blog.csdn.net/huangdingsheng/article/details/104414492
今日推荐