3、进一步泛化,在一组随机排列的数中找出第k小的,这个元素称为k-th Order Statistic。能想到的最直观的算法肯定是先把这些数排序然后取第k个,时间复杂度和排序算法相同,可以是Θ(nlgn)。这个问题虽然比前两个问题复杂,但它也有平均情况下时间复杂度是Θ(n)的算法,将上一节习题1的快速排序算法稍加修改就可以解决这个问题:
/* 第k小的元素在start和end之间,找出并返回该元素 */ int order_statistic(int start, int end, int k) { 用partition函数把序列分成两部分,中间的pivot元素是序列中的第i个; if (k == i) 返回找到的元素; else if (k > i) 第k小的元素在序列后半部分,找出并返回该元素; else 第k小的元素在序列前半部分,找出并返回该元素; }
请编程实现这个算法。
注:转载请注明源地址:http://blog.csdn.net/whorus1/article/details/21075085,谢谢!
#include<stdio.h> #define LEN 7 #define k 1 int a[LEN] = {4, 2, 5, 8, 3, -9, 6}; void swap(int c, int b) { int tmp; if (a[c] > a[b]) { tmp = a[c]; a[c] = a[b]; a[b] = tmp; } return; } int main() { int i, j; for (i = 0; i < k; i ++) { for (j = i + 1; j < LEN; j++) { swap(i, j); } } printf ("%d\n",a[k - 1]); return 0; }
#include <stdio.h> #define LEN 7 #define k 1 int a[LEN] = {4, 2, 5, 8, 3, -9, 6}; void swap(int i, int j) { int tmp; if (a[i] > a[j]) { tmp = a[i]; a[i] = a[j]; a[j] = tmp; } return; } int order_statistic(int start, int end){ int select = a[end-1]; int i = start; int j = end - 2; while (i <= j) { while (a[i] < select) i++; while (a[j] >= select) j--; swap(i, j); i++; j--; } swap(i, end-1); if (k == i) { return a[k]; } else if (k > i) { return order_statistic(i+1, end); } else { return order_statistic(start, i); } } int main(void) { printf("The num in %d is: %d\n", k, order_statistic(0, LEN)); }