您的位置:首页 > 其它

《算法导论》第九章----中位数和顺序统计学

2013-10-11 22:03 246 查看
《算法导论》学习记录目录

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

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

最小值最大值

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

#include <stdio.h>
#include <stdlib.h>

int randomized_partition(int A[], int p, int r);

int partition(int A[], int p, int r);

int randomized_select(int A[], int p, int r, int i);

int randomized_select_iteration(int A[], int p, int r, int i);

int main(){
int number;
scanf("%d", &number);
int *array = malloc(number * sizeof(int));

int i;
for(i = 0; i < number; i++)
scanf("%d", &array[i]);

int which;
scanf("%d", &which);

//int select = randomized_select(array, 0, number-1, which);
int select = randomized_select_iteration(array, 0, number-1, which);
printf("%d\n", select);
return 0;
}

int randomized_partition(int A[], int p, int r){
int i = p + rand() % (r - p + 1);
int temp = A[i];
A[i] = A[r];
A[r] = temp;
return partition(A, p, r);
}

int partition(int A[], int p, int r){
int x = A[r];
int i = p - 1;
int j;
for(j = p; j <= r -1; j++){
if(A[j] <= x){
i++;
int temp = A[i];
A[i] = A[j];
A[j] = temp;
}
}
int temp = A[i+1];
A[i+1] = A[r];
A[r] = temp;

return i+1;
}

/*
* 在数组下标为p到r中找出第i小的元素
*/
int randomized_select(int A[], int p, int r, int i){
if(p == r)
return A[p];
int q = randomized_partition(A, p, r);       //在下标为p到r中随机找一个元素,以该元素为主元素划分数组,并返回该元素的位置
int k = q - p + 1;                          //主元素在数组下标为p到r中里为第几小的元素

if(i == k)                                 //如果i等于k,主元素为要找的值
return A[q];
else if(i < k)                              //如果i小于k,说明要找的第i小的元素比主元素要小,所以只出现在主元素的左边的子数组里,而这时,第i小的元素在左边子数组依然为第i小。
return randomized_select(A, p, q-1, i);
else                                            //如果i大于,说明要找的第i小元素比主元素要大,所以只出现在主元素的右边的子数组里,而这时,第i小的元素在右边子数组应该为i-k小。子数组的位置为q+1,而q位置的元素为第k小的元素。
return randomized_select(A, q+1, r, i-k);
}

/*
* 下面为迭代实现
*/
int randomized_select_iteration(int A[], int p, int r, int i){
if(p == r)
return A[p];

while(1){
int q = randomized_partition(A, p, r);
int k = q - p + 1;

if(i == k)
return A[q];
else if(i < k){
r = q - 1;
}
else{
p = q + 1;
i = i - k;
}
}
}


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

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

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

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

继续努力!!!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐