zoukankan      html  css  js  c++  java
  • 《算法导论》第九章----中位数和顺序统计学

    《算法导论》学习记录目录

    本章主要讲了如何在一个集合里找出第i个顺序统计量(即第i个小的元素),可以定义选择问题(n个元素中的第i个小的元素,即在n个元素里找出一个元素,这个元素大于其他i-1个元素)。

    如果我们用堆排序或合并排序(Ο(nlgn))对该集合进行排序,然后直接找出第i个元素即可。这样一来,选择问题运行时间为Ο(nlgn)。但是本章讲其他两种方法可以使的选择问题的运行时间为O(n),分别为以期望线性时间做选择和最坏情况线性时间的选择。(PS:本人能力不足,对于最坏情况线性时间的选择的算法还在看,不能将其实现。。。。所以下文不会出现。。。)

    最小值最大值

    最小值和最大值都可以通过n-1次比较找出,先假设最小值(最大值)为第一个元素,再与剩下的元素比较,在比较过程中找出最小值(最大值)。

     1 int minimum(int A[], int length){
     2     int min = A[0];
     3     int i;
     4     for(i = 1; i < length; i++){
     5         if(min > A[i])
     6             min = A[i];
     7     }
     8 
     9     return min;
    10 }
    minimun

    同时找出最小值最大值

    如果独立找出最小值和最大值总共用了2n-2次比较。但是可以用3*floor(n / 2)次比较就可以同时找出最小值和最大值。方法为成对进行比较,先一对元素互相比较,然后较小的元素与最小值比较,较大的元素与最大值比较,这样每两个元素只需要比较3次。对于最小值和最大值初值,我们将元素数目分为奇偶数两种处理:如果为奇数,最小值和最大值的初值都为第一个元素的值,然后成对处理;如果为偶数,第一对元素先比较,较小的为最小值的初值,较大的为最大值的初值。

     1 #include <stdio.h>
     2 #include <stdlib.h>
     3 
     4 int main(){
     5     int number, i;
     6     int min, max;
     7     int t_max, t_min;
     8     scanf("%d", &number);
     9     int *array = malloc(number * sizeof(int));
    10     
    11     for(i = 0; i < number; i++)
    12         scanf("%d", &array[i]);
    13 
    14     if(number % 2){                 //奇数
    15         min = max = array[0];
    16         i = 1;
    17     }
    18     else{                           //偶数
    19         if(array[0] > array[1]){
    20             max = array[0];
    21             min = array[1];
    22         }
    23         else{
    24             max = array[1];
    25             min = array[0];
    26         }
    27         i = 2;
    28     }
    29 
    30     for(; i < number; i += 2){
    31         if(array[i] > array[i+1]){  //每对元素先进行比较
    32             t_max = array[i];
    33             t_min = array[i+1];
    34         }
    35         else{
    36             t_max = array[i+1];
    37             t_min = array[i];
    38         }
    39         
    40         if(t_max > max)             //较大的元素与最大值比较
    41             max = t_max;
    42         if(t_min < min)             //较小的元素与最大值比较
    43             min = t_min;
    44     }
    45 
    46     printf("Min is %d, Max is %d.
    ", min, max);
    47     return 0;
    48 }
    minmax

    以期望线性时间做选择

    很多人会觉得在n个元素里面找出第i个小的值会比找出最小值要困难,但是以期望线性时间做选择的算法的渐进运行时间为Θ(n)。本章介绍的该算法是分治算法,以快速排序算法为基础,对数组进行递归划分。但是该算法不需要对划分的两边进行处理,而只需要处理划分的一边,这样一来该算法的期望运行时间为Θ(n)。

    该算法为随机算法,使用了快速排序中的随机化版本(链接在此)的randomized_partition方法(PS:调用方法的注释见前链接)。

    代码中还有迭代版本(练习9.2-3)

     1 #include <stdio.h>
     2 #include <stdlib.h>
     3 
     4 int randomized_partition(int A[], int p, int r);
     5 
     6 int partition(int A[], int p, int r);
     7 
     8 int randomized_select(int A[], int p, int r, int i);
     9 
    10 int randomized_select_iteration(int A[], int p, int r, int i);
    11 
    12 int main(){
    13     int number;
    14     scanf("%d", &number);
    15     int *array = malloc(number * sizeof(int));
    16 
    17     int i;
    18     for(i = 0; i < number; i++)
    19         scanf("%d", &array[i]);
    20 
    21     int which;
    22     scanf("%d", &which);
    23 
    24     //int select = randomized_select(array, 0, number-1, which);
    25     int select = randomized_select_iteration(array, 0, number-1, which);
    26     printf("%d
    ", select);
    27     return 0;
    28 }
    29 
    30 int randomized_partition(int A[], int p, int r){
    31     int i = p + rand() % (r - p + 1);
    32     int temp = A[i];
    33     A[i] = A[r];
    34     A[r] = temp;
    35     return partition(A, p, r);
    36 }
    37 
    38 int partition(int A[], int p, int r){
    39     int x = A[r];
    40     int i = p - 1;
    41     int j;
    42     for(j = p; j <= r -1; j++){
    43         if(A[j] <= x){
    44             i++;
    45             int temp = A[i];
    46             A[i] = A[j];
    47             A[j] = temp;
    48         }
    49     }
    50     int temp = A[i+1];
    51     A[i+1] = A[r];
    52     A[r] = temp;
    53 
    54     return i+1;
    55 }
    56 
    57 /*
    58  * 在数组下标为p到r中找出第i小的元素
    59  */
    60 int randomized_select(int A[], int p, int r, int i){
    61     if(p == r)
    62         return A[p];
    63     int q = randomized_partition(A, p, r);       //在下标为p到r中随机找一个元素,以该元素为主元素划分数组,并返回该元素的位置
    64     int k = q - p + 1;                          //主元素在数组下标为p到r中里为第几小的元素
    65     
    66     if(i == k)                                 //如果i等于k,主元素为要找的值
    67         return A[q];
    68     else if(i < k)                              //如果i小于k,说明要找的第i小的元素比主元素要小,所以只出现在主元素的左边的子数组里,而这时,第i小的元素在左边子数组依然为第i小。
    69         return randomized_select(A, p, q-1, i);
    70     else                                            //如果i大于,说明要找的第i小元素比主元素要大,所以只出现在主元素的右边的子数组里,而这时,第i小的元素在右边子数组应该为i-k小。子数组的位置为q+1,而q位置的元素为第k小的元素。
    71         return randomized_select(A, q+1, r, i-k);
    72 }
    73 
    74 
    75 /*
    76  * 下面为迭代实现
    77  */
    78 int randomized_select_iteration(int A[], int p, int r, int i){
    79     if(p == r)
    80         return A[p];
    81 
    82     while(1){
    83         int q = randomized_partition(A, p, r);
    84         int k = q - p + 1;
    85 
    86         if(i == k)
    87             return A[q];
    88         else if(i < k){
    89             r = q - 1;
    90         }
    91         else{
    92             p = q + 1;
    93             i = i - k;
    94         }
    95     }
    96 }
    randomized_select

    这个算法看起来会递归调用含有0个元素的子数组,但是这种情况不会发生。(长度为0的数组,会直接返回,不会递归调用)

    这个算法的最坏情况运行时间为Θ(n2),即每次划分都是按余下的元素中最大的进行划分。但是该算法的平均情况性能较好,而且是随机化,故没有哪一种特殊的输入会导致最坏情况的发生。

    具体关于期望的计算请见算导原文。。。。(有很多的计算和证明还在看。。。。)

    虽然本章的页数很少,但是有很多习题和思考题。。。。以后一定要好好做了,并把最坏情况线性时间的选择也补上。。。。

    继续努力!!!

  • 相关阅读:
    对于HTTP过程中POST内容加密的解决方案
    电脑重启后IDEA项目中import class 报错
    前端Button点击无反应--记一次Debug经历
    plsql 中substr函数和instr函数的灵活应用
    浅谈Plsql 中inner join 和left join的使用
    Mysql查询优化
    Mysql单机安裝
    centos查看文件被哪个进程占用
    jvm垃圾收集器详解
    navicat破解
  • 原文地址:https://www.cnblogs.com/alan-forever/p/3364281.html
Copyright © 2011-2022 走看看