首页 > 代码库 > 算法导论-------------中位数和顺序统计学
算法导论-------------中位数和顺序统计学
文章来自网络加课本:
本次学习的内容讨论的问题是在一个由n个不同数值构成的集合中选择第i个顺序统计量问题。主要讲的内容是如何在线性时间内O(n)时间内在集合S中选择第i小的元素,最基本的是选择集合的最大值和最小值。一般情况下选择的元素是随机的,最大值和最小值是特殊情况,书中重点介绍了如何采用分治算法来实现选择第i小的元素,并借助中位数进行优化处理,保证最坏保证运行时间是线性的O(n)。
1、基本概念
顺序统计量:在一个由n个元素组成的集合中,第i个顺序统计量是值该集合中第i小的元素。例如最小值是第1个顺序统计量,最大值是第n个顺序统计量。
中位数:一般来说,中位数是指它所在集合的“中间元素”,当n为奇数时,中位数是唯一的,出现位置为n/2;当n为偶数时候,存在两个中位数,位置分别为n/2(上中位数)和n/2+1(下中位数)。
2、选择问题描述
输入:一个包含n个(不同的)数的集合A和一个数i,1≤i≤n。
输出:元素x∈A,它恰大于A中其他的i-1个元素。
最直接的办法就是采用一种排序算法先对集合A进行排序,然后输出第i个元素即可。可以采用前面讲到的归并排序、堆排序和快速排序,运行时间为O(nlgn)。接下来书中由浅入深的讲如何在线性时间内解决这个问题。
3、最大值和最小值
要在集合中选择最大值和最小值,可以通过两两元素比较,并记录最大值和最小值,n元素的集合需要比较n-1次,这样运行时间为O(n)。举个例子来说明,现在要求和集合A={32,12,23,67,45,78}的最大值,开始假设第一个元素最大,即max=1,然后从第二个元素开始向后比较,记录最大值的位置。执行过程如下图所示:
书中给出的求最小值的伪代码如下:
1 MINMUN(A) 2 min = A[1] 3 for i=1 to length(A) 4 do if min > A[i] 5 then min >= A[i] 6 return min
问题:
(1)同时找出集合的最大值和最小值
方法1:按照上面讲到的方法,分别独立的找出集合的最大值和最小值,各用n-1次比较,共有2n-2次比较。
方法2:可否将最大值和最小值结合在一起寻找呢?答案是可以的,在两两比较过程中同时记录最大值和最小值,这样最大需要3n/2次比较。现在的做法不是将每一个 输入元素与当前的最大值和最小值进行比较,而是成对的处理元素,先将一对输入元素进行比较,然后把较大者与当前最大值比较,较小者与当前最小者比较,因此每两个元素需要3次比较。初始设置最大值和最小值方法:如何n为奇数,就将最大值和最小值都设置为第一个元素的值,然后成对的处理后续的元素。如果n为偶数,那么先比较前面两个元素的值,较大的设置为最大值,较小的设置为最小值,然后成对处理后续的元素。这样做的目的保证能够成对的处理后续的元素。举个例子说明这个过程,假设现在要找出集合A={32,23,12,67,45,78,10,39,9,58}最大值和最小值,执行过程如下:
#include<iostream> using namespace std; void get_max_min(int a[],int len, int *max, int *min) { int tmp_max, tmp_min; if (len % 2 == 0) { if (a[0] > a[1]) { *max = a[0]; *min = a[1]; } else{ *max = a[1]; *min= a[0]; } for (int i = 2; i < len; i = i + 2) { if (a[i]>a[i + 1]) { tmp_max = a[i]; tmp_min = a[i + 1]; } else { tmp_max = a[i + 1]; tmp_min = a[i]; } if (*max < tmp_max) *max = tmp_max; if (*min>tmp_min) *min = tmp_min; } } else { *max = a[0]; *min = a[0]; for (int i = 1; i < len; i = i + 2) { if (a[i]>a[i + 1]) { tmp_max = a[i]; tmp_min = a[i + 1]; } else { tmp_max = a[i + 1]; tmp_min = a[i]; } if (*max < tmp_max) *max = tmp_max; if (*min>tmp_min) *min = tmp_min; } } } int main() { int a[] = { 23, 12, 34, 26, 78, 45, 87, 15, 60, 19, 11 }; int len = sizeof(a) / sizeof(int); cout << len << endl; int max_value, min_value; get_max_min(a, len, &max_value, &min_value); cout << max_value << endl; cout << min_value << endl; return 0; }
算法导论-------------中位数和顺序统计学