算法导论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 partition(int64_t* A, int64_t p, int64_t r)
{
    int64_t x = A[r];
    int64_t i = p;
    for (int64_t j = p; j < r; j++)
    {
        if (A[j] <= x)
        {
            swap(A, i, j);
            i++;
        }
    }
    swap(A, i, r);
    return i;
}

int64_t RandomizedPartition(int64_t* A, int64_t p, int64_t r)
{
    int64_t i = (rand() % (r - p)) + p;
    swap(A, i, r);
    return partition(A, p, r);
}

// RANDOMIZED-SELECT(A, p, r, i)
// if p == r
//     return A[p]
// q = RANDOMIZED-PARTITION(A, p, r)
// k = q - p + 1
// if i == k
// return A[q]
// else if i < k
//     return RANDOMIZED-SELECT(A, p, q - 1, i)
// else
//     return RANDOMIZED-SELECT(A, q + 1, r, i - k)

int64_t RandomizedSelect(int64_t* A, int64_t p, int64_t r, int64_t i)
{
    if (p == r)
    {
        return A[p];
    }
    int64_t q = RandomizedPartition(A, p, r);
    int64_t k = q - p + 1;
    if (i == k)
    {
        return A[q];
    }
    else if (i < k)
    {
        return RandomizedSelect(A, p, q - 1, i);
    }
    else
    {
        return RandomizedSelect(A, q + 1, r, i - k);
    }
}
int main()
{
    int64_t array[] = { 2, 8, 7, 1, 3, 5, 6, 4 };

    std::cout << RandomizedSelect(array, 0, 7, 3) << std::endl;
    getchar();
    return 0;
}
BIN     = bin
FMCSA   = find_max_crossing_subarray
IAS     = IA_solution
IST     = insertion_sort_t
LMSA    = liner_time_max_subarray
MERGE   = merge
MERGE_T = merge_t
VMS     = violate_max_subarray
STRA    = 4.2_strassen
COUNT_SORT = 8.2_counting_sort
MINIMUMMAXIMUM = 9.1_MinimumMaximum
RS = 9.2_RandomizedSelect
RQ = 7.3_RandomizedQuicksort
QS = 7.1_quicksort

CFLAGS = -g -Wall

all : ${BIN}/${COUNT_SORT} ${BIN}/${RS} ${BIN}/${QS} ${BIN}/${FMCSA} ${BIN}/${RQ} ${BIN}/${IAS} ${BIN}/${IST} ${BIN}/${LMSA} ${BIN}/${MERGE} ${BIN}/${MERGE_T} ${BIN}/${VMS} ${BIN}/${STRA} ${BIN}/${MINIMUMMAXIMUM}

${BIN}/${COUNT_SORT} : ${COUNT_SORT}/counting_sort.cpp
	g++ ${COUNT_SORT}/counting_sort.cpp ${CFLAGS} -o ${BIN}/${COUNT_SORT}

${BIN}/${FMCSA} : ${FMCSA}/main.cpp ${FMCSA}/max_sub_array.h
	g++ ${FMCSA}/main.cpp ${CFLAGS} -o ${BIN}/${FMCSA}

${BIN}/${IAS} : ${IAS}/insertion_sort.cpp ${IAS}/insertion_sort.h
	g++ ${IAS}/insertion_sort.cpp ${CFLAGS} -o ${BIN}/${IAS}

${BIN}/${IST} : ${IST}/${IST}.cpp ${IST}/${IST}.h
	g++ ${IST}/${IST}.cpp ${CFLAGS} -o ${BIN}/${IST}

${BIN}/${LMSA} : ${LMSA}/Source.cpp
	g++ ${LMSA}/Source.cpp ${CFLAGS} -o ${BIN}/${LMSA}

${BIN}/${MERGE} : ${MERGE}/${MERGE}.cpp  ${MERGE}/${MERGE}.h
	g++ -std=c++0x ${MERGE}/${MERGE}.cpp ${CFLAGS} -o ${BIN}/${MERGE}

${BIN}/${MERGE_T} : ${MERGE_T}/${MERGE_T}.cpp  ${MERGE_T}/${MERGE_T}.h
	g++ -std=c++0x ${MERGE_T}/${MERGE_T}.cpp ${CFLAGS} -o ${BIN}/${MERGE_T}

${BIN}/${VMS} : ${VMS}/Source.cpp
	g++ ${VMS}/Source.cpp ${CFLAGS} -o ${BIN}/${VMS}

${BIN}/${STRA} : ${STRA}/strassen.cpp ${STRA}/strassen.h
	g++ -std=c++0x ${STRA}/strassen.cpp ${CFLAGS} -o ${BIN}/${STRA}

${BIN}/${MINIMUMMAXIMUM} : ${MINIMUMMAXIMUM}/${MINIMUMMAXIMUM}.cpp
	g++ ${MINIMUMMAXIMUM}/${MINIMUMMAXIMUM}.cpp ${CFLAGS} -o ${BIN}/${MINIMUMMAXIMUM}

${BIN}/${RS} : ${RS}/${RS}.cpp
	g++ ${RS}/${RS}.cpp ${CFLAGS} -o ${BIN}/${RS}

${BIN}/${RQ} : ${RQ}/${RQ}.cpp
	g++ ${RQ}/${RQ}.cpp ${CFLAGS} -o ${BIN}/${RQ}

${BIN}/${QS} : ${QS}/${QS}.cpp ${QS}/${QS}.h
	g++ ${QS}/${QS}.cpp ${CFLAGS} -o ${BIN}/${QS}

clean:
	rm ${BIN}/*

时间: 2024-11-04 10:16:33

算法导论9.2以期望线性时间做选择的相关文章

【算法导论-学习笔记】以线性时间增长的排序——计数排序

计数排序是一种能够达到运行时间能够线性时间θ(n)的排序算法.在排序算法里算是最快的算法之一,当然,他有很强烈的前提.下面开始介绍一下技术排序(Counting Sort). 算法思想 计数排序假设n个输入元素中的每一个都是介于0到k之间的整数,此处k为某个整数.这样可以用一个数组C[0..k]来记录待排序数组里元素的数量.当k=O(n)时,计数排序的运行时间为θ(n). 注:关于C[0..k],用键值对描述的话,待排序元素是键,相同元素的个数是值.例:待排序数组<2,3 , 6,4 , 1 ,

算法导论笔记 第8章 线性时间排序

任何比较排序在最好情况下都要经过Ω(nlgn),即比较排序的下界为Ω(nlgn). 合并排序和堆排序都是渐进最优的. 要突破Ω(nlgn),就要进行非比较排序.计数排序.基数排序和桶排序都有非比较的一些操作来确定排序顺序,它们可以达到线性运行时间. 这三种排序都是以空间换时间.应用的不广,先不细看了. 原文地址:https://www.cnblogs.com/jackson-zhou/p/8419798.html

第九章 中位数和顺序统计量 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

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

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

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

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

期望为线性时间的选择算法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[

中位数和顺序统计,以线性期望时间做选择

找出一个数组的最大值和最小值是比较容易的,我们只需遍历一次数组即可.但是寻找一个数组的第i小或者第i大,就需要一些技巧使得查找的时间尽可能小.随机化划分选择算法是一个时间复杂度为O(n)的算法. int fIndmax(int a[],int p,int r,int i) { if(p==r) return a[p]; int q = RandPartition(a, p, r); // A[q]作为主元将A[p...r]进行划分. int k = q - p + 1; //假设k是要查找的第i

《算法导论》读书笔记(三)

本章介绍了快速排序及其算法分析,快速排序采用的是分治算法思想,对包含n个数的输入数组,最坏情况下运行时间为θ(n^2),但是平均性能相当好,期望的运行时间为θ(nlgn).另外快速排序能够就地排序(我理解是不需要引入额外的辅助空间,每次划分能确定一个元素的具体位置),在虚拟环境中能很好的工作. 1.快速排序的描述 快速排序算法采用的分治算法,因此对一个子数组A[p-r]进行快速排序的三个步骤为: (1)分解:数组A[p...r]被划分为两个(可能为空)子数组A[p...q-1]和A[q+1...