期望为线性时间的选择算法

randomized_select函数的期望运行时间是Θ(n),这里假设输入数据都是互异的.它返回数组A[p, r]中第i小的元素.该函数最坏情况运行时间为Θ(n2),即使是找最小元素也是如此,以为在每次划分时可能极不走运地总是按余下的元素中最大的来进行划分,而划分操作需要Θ(n)时间.我们也将看到该算法有线性的期望运行时间,又因为它是随机化的,所以不存在一个特定的会导致其最坏情况发生的输入数据.

输入:数组A,整数i(i不大于数组的个数).

输出:数组A中第i小的元素.

期望运行时间:Θ(n).最坏运行时间:Θ(n2).

  1 #include <stdio.h>
  2 #include <stdlib.h>
  3 #include <time.h>
  4
  5 static int randomized_select(int *, int, int, int);
  6 static int randomized_partition(int *, int, int);
  7 static int partition(int *, int, int);
  8 static int randomd(int, int);
  9 static void swap(int *, int *);
 10
 11
 12 int main(int argc, char *argv[])
 13 {
 14
 15     int mid;
 16     int array[9] = {1,2,4,7,3,5,6,8,12};     /*返回第5小的元素.*/
 17     mid = randomized_select(array, 0, 8, 5);
 18     printf("%d\n", mid);
 19     return 0;
 20 }
 21
 22
 23 static int randomized_select(int *A, int p, int r, int i)
 24 {
 25     int q, k;
 26
 27     if (p == r)
 28         return A[p];
 29
 30     q = randomized_partition(A, p, r);
 31     k = q - p + 1;
 32
 33     if (i == k)
 34         return A[q];
 35     else if (i < k)
 36         return randomized_select(A, p, q - 1, i);
 37     else
 38         return randomized_select(A, q + 1, r, i - k);
 39 }
 40
 41 static int randomized_partition(int *A, int p, int r)
 42 {
 43     int i, temp;
 44     i = randomd(p, r);
 45     swap(A + r, A + i);
 46 /*
 47     temp = A[r];
 48     A[r] = A[i];
 49     A[i] = temp;
 50 */
 51     return partition(A, p, r);
 52 }
 53 /*划分,跟快速排序一样.*/
 54 static int partition(int *A, int p, int r)
 55 {
 56     int a, i, j, temp;
 57     a = A[r];
 58     i = p - 1;
 59
 60     for (j = p; j < r; ++j)
 61     {
 62         if (A[j] <= a)
 63         {
 64             ++i;
 65             swap(A + j, A + i);
 66         /*
 67             temp = A[j];
 68             A[j] = A[i];
 69             A[i] = temp;
 70         */
 71         }
 72
 73     }
 74
 75     swap(A + r, A + i + 1);
 76 /*
 77     temp = A[r];
 78     A[r] = A[i + 1];
 79     A[i + 1] = temp;
 80 */
 81     return i + 1;
 82 }
 83
 84 /*返回特定范围[a, b]内的一个随机数.*/
 85 static int randomd(int a, int b)
 86 {
 87     int q;
 88
 89     srand((unsigned int)time(NULL));
 90     q = rand()%(b - a + 1) + a;
 91
 92     return q;
 93 }
 94
 95 /*交换值.*/
 96 static void swap(int *num1, int *num2)
 97 {
 98     int temp;
 99     temp = *num1;
100     *num1 = *num2;
101     *num2 = temp;
102 }
时间: 2024-10-22 17:24:55

期望为线性时间的选择算法的相关文章

第九章 中位数和顺序统计量 9.2 期望为线性时间的选择算法

package chap09_Medians_and_Order_Statistics; import static org.junit.Assert.*; import java.util.Random; import org.junit.Test; public class SearchAlorithms { /** * 分割(快速排序中对数组的分割) * * @param n * @param start * @param end * @return */ protected static

期望为线性时间的选择算法RANDOM_SELECT

1 #include<iostream> 2 #include<ctime> 3 using namespace std; 4 void swap(int *a, int *b) 5 { 6 int *c = a; 7 a = b; 8 b = c; 9 } 10 int Partition(int *A, int p, int r)// 划分 11 { 12 int x = A[r]; 13 int i = p - 1; 14 for (int j = p; j < r;

平均期望为线性时间的选择算法

从一组无序数据中选择出第i小的元素,采用了快速排序的思想. #include <iostream> #include <algorithm> using namespace std; int partition(int a[], int l, int r){ int key = a[l]; int i=l; swap(a[l],a[r]); for(int j=l;j<r;j++) if(a[j]<key) swap(a[i++],a[j]); swap(a[i],a[

最坏情况为线性时间的选择算法

求给定输入中第k大的数的算法. 这是一个常见面试题,通常的解法也很明显,使用类似快排的思想. 每趟运行,把数组的值分成两部分,一部分比pivot大,一部分比pivot小,因为我们知道pivot在数组中的位置,所以比较k和pivot的位置就知道第k大的值在哪个范围,我们不断的进行recursion, 直到pivot就是第k大的值. 这个算法的时间预期是O(n).这里需要注意的是讲的仅限于它的预期,对于这个算法,其在最差情况下,时间复杂度则为n的平法. 参阅快速排序的无敌对手一文,我们是可以构建出一

算法导论9.2以期望线性时间做选择

#include <stdint.h> #include <time.h> #include <iostream> #ifdef __linux #include <stdio.h> #include <stdlib.h> #endif void swap(int64_t* A, uint64_t i, uint64_t j) { int64_t tmp = A[i]; A[i] = A[j]; A[j] = tmp; } int64_t par

算法导论学习之线性时间排序+排序算法稳定性终结

前面我们学习的几种排序算法都是基于比较的,对于任何输入数据他们都是适用的,其最坏的时间复杂度不会低于nlgn: 但对于一些比较特殊的输入数据,我们可以不采取比较的方法而是采用其它的方法对其进行排序,以达到线性的时间复杂度.下面就来介绍三种这样的算法:计数排序,基数排序,桶排序(因为这几种算法不常见,我只实现了计数排序,其它两种排序用伪代码表示). 一.计数排序 算法思想:给定n个位于0–k之间的数(k是一个不太大的整数),我们可以统计出每个数前面有多少个小于它的数,然后就可以直接确定这个数在数组

算法导论——lec 08 线性时间排序

之前我们介绍了几种O(nlgn)的排序算法:快速排序.合并排序和堆排序,本节我们介绍基于比较的排序算法的下界以及几个线性时间的排序算法--计数排序.基数排序.桶排序. 一. 比较排序算法的下界 1. 决策树模型:比较排序可以被抽象的视为决策树.一棵决策树是一棵满二叉树,表示某排序算法 作用于给定输入所做的所有比较. 排序算法的执行对应于遍历一条从树的根到叶结点的路径.在每个内节结点处要做比较. 要使排序算法能正确的工作,其必要条件是,n 个元素的n!种排列中的每一种都要作为决策树 的一个叶子而出

排序算法(4)-线性时间排序

在前面三节排序算法中,我们分别分析了不同策略,思想用于排序,而这些算法都是基于数据间的比较来确定顺序的.假设我不用比较,换一种思路,那么就可以达到时间复杂度为O(n)的排序算法,当然是以付出额外的空间为代价的. 一.基本思想 线性时间排序的算法思想: (1):在计数排序中,利用比x小或等的元素个数和的来确定x位置.比如2 5 4 9 1 6.9比其余5个数都大,那就说明9 在排序后的第6个位置,这样我们只要得到比某个数大的元素个数就能得到元素在排序后数组中的位置了. (2):在桶排序中,是通过映

读书日记- 线性时间排序算法

在最坏情况下,任何比较排序算法都需要做O(nlgn)次比较. 然而,在指定的条件下,线性时间的排序算法可以使得排序在O(n)时间内完成. 计数排序 假设n个输入元素中的每一个都是0到k区间内的一个整数,其中k为某个整数.k=O(n)时,排序运行时间为O(n). 主要思想: 创建长度为k的数组C,将对应的输入数组A的值作为索引来统计k数组每个下标出现的次数. 代码如下: void Counting_Sort(int* intArr,int* outArr,int k,int len) { int*