• 快速选择算法


    利用快速排序的思想,选择第k大(或小)的数。

    具体地,利用快速排序的划分思想,每次将数组划分为两部分,确定该第k大(或小)的元素在哪一个部分,然后对该部分递归进行划分,直到找到第k大(或小)的元素。快速排序期望时间复杂度为O(n log n),快速选择算法期望时间复杂度为O(n)

    关于枢纽元的选择:

    1. 选取第一个或最后一个元素,一般做法。
    2. 三数取中值法。取首、中、尾3个位置的元素的中间值,并将该中间值交换至第一个或最后一个元素,继续同1进行排序。
    3. 中位数的中位数法。
      1. 将所有元素进行组分,如每5个为一组,可分为[n/5]组。
      2. 对每个组进行排序,并得到该组的中位数。
      3. 递归调用步骤 a, b 直到获得最终的中位数。

    快速选择算法的一个实现:(三值取中值法)

     1 package com.yan.algorithmTest;
     2 
     3 /**
     4  * quick select algorithm which is very similar to quick sort algorithm.
     5  * it suffers the average complication of O(n), while quick sort algorithm suffers O(n log n).
     6  * @author Yan
     7  *
     8  */
     9 public class QuickSelectTest {
    10     private static int[] data = new int[] { 5, 3, 4, 6, 2, 1, 7, 8, 10, 9 };
    11     private static int k = 4;
    12 
    13     public QuickSelectTest() {
    14     }
    15 
    16     public static void main(String[] args) {
    17         int result = quickSelect(data, k, 0, data.length - 1);
    18         System.out.println(result);
    19     }
    20 
    21     public static int quickSelect(int[] data, int k, int start, int end) {
    22         if (k > data.length || start > end) {
    23             return -1;
    24         }
    25         /*
    26          * 与quick sort 相同的partition算法(分割算法)。
    27          */
    28         int pivot = end;
    29         int left = start;
    30         int right = end;
    31         while (left < right) {
    32             while (data[left] <= data[pivot] && left < right) {
    33                 left++;
    34             }
    35             while (data[right] >= data[pivot] && left < right) {
    36                 right--;
    37             }
    38             swap(data, left, right);
    39         }
    40         swap(data, left, pivot);
    41         /*
    42          * 与快速排序相同,只是在recurse时,多了两个判断,即k的判断。因此,只有一个递归调用会执行。 相较于快速排序的期望时间复杂度O(n
    43          * log n),快速选择的期望时间复杂度为O(n)。
    44          */
    45         if (k - 1 > left) {
    46             quickSelect(data, k, left + 1, end);
    47         }
    48         if (k - 1 < left) {
    49             quickSelect(data, k, start, left - 1);
    50         }
    51 
    52         return data[k - 1];
    53     }
    54 
    55     /*
    56      * median-of-three,三值取中值法,获取首、中、尾三者中得中间值,并与枢纽元pivot,即尾(或首)交换。
    57      */
    58     public static void medianPivot(int[] data, int start, int end) {
    59         int center = (start + end) >> 1;
    60         if (data[start] > data[center]) {
    61             swap(data, start, center);
    62         }
    63         if (data[center] > data[end]) {
    64             swap(data, end, center);
    65         }
    66         if (data[start] > data[end]) {
    67             swap(data, end, start);
    68         }
    69         swap(data, end, center);
    70     }
    71 
    72     public static void swap(int[] data, int x, int y) {
    73         int temp = data[x];
    74         data[x] = data[y];
    75         data[y] = temp;
    76     }
    77 }
  • 相关阅读:
    【世界上最优秀的逆向分析工具】IDA Pro6.1绿色版
    js 在线压缩混淆工具
    [转载 js]网站开发常用的一些值得珍藏的代码
    js 和 as 保留指定小数位数
    js 在线压缩混淆工具
    DOM元素的所有子元素 .elements
    DOM元素的所有子元素 .elements
    [转载 js]网站开发常用的一些值得珍藏的代码
    关于 getElementsByTagName
    js 和 as 保留指定小数位数
  • 原文地址:https://www.cnblogs.com/yanspecial/p/5551222.html
Copyright © 2020-2023  润新知