算法设计与分析线性时间选择讲解文档
《算法设计与分析》实验指导书_bfm(全)

《算法设计与分析》实验指导书本书是为配合《算法分析与设计实验教学大纲》而编写的上机指导,其目的是使学生消化理论知识,加深对讲授内容的理解,尤其是一些算法的实现及其应用,培养学生独立编程和调试程序的能力,使学生对算法的分析与设计有更深刻的认识。
上机实验一般应包括以下几个步骤:(1)、准备好上机所需的程序。
手编程序应书写整齐,并经人工检查无误后才能上机。
(2)、上机输入和调试自己所编的程序。
一人一组,独立上机调试,上机时出现的问题,最好独立解决。
(3)、上机结束后,整理出实验报告。
实验报告应包括:题目、程序清单、运行结果、对运行情况所作的分析。
本书共分阶段4个实验,每个实验有基本题和提高题。
基本题必须完成,提高题根据自己实际情况进行取舍。
题目不限定如下题目,可根据自己兴趣爱好做一些与实验内容相关的其他题目,如动态规划法中的图象压缩,回溯法中的人机对弈等。
其具体要求和步骤如下:实验一分治与递归(4学时)一、实验目的与要求1、熟悉C/C++语言的集成开发环境;2、通过本实验加深对递归过程的理解二、实验内容:掌握递归算法的概念和基本思想,分析并掌握“整数划分”问题的递归算法。
三、实验题任意输入一个整数,输出结果能够用递归方法实现整数的划分。
四、实验步骤1.理解算法思想和问题要求;2.编程实现题目要求;3.上机输入和调试自己所编的程序;4.验证分析实验结果;5.整理出实验报告。
一、实验目的与要求1、掌握棋盘覆盖问题的算法;2、初步掌握分治算法二、实验题:盘覆盖问题:在一个2k×2k个方格组成的棋盘中,恰有一个方格与其它方格不同,称该方格为一特殊方格,且称该棋盘为一特殊棋盘。
在棋盘覆盖问题中,要用图示的4种不同形态的L型骨牌覆盖给定的特殊棋盘上除特殊方格以外的所有方格,且任何2个L型骨牌不得重叠覆盖。
三、实验提示void chessBoard(int tr, int tc, int dr, int dc, int size) {if (size == 1) return;int t = tile++, // L型骨牌号s = size/2; // 分割棋盘// 覆盖左上角子棋盘if (dr < tr + s && dc < tc + s)// 特殊方格在此棋盘中chessBoard(tr, tc, dr, dc, s);else {// 此棋盘中无特殊方格// 用t 号L型骨牌覆盖右下角board[tr + s - 1][tc + s - 1] = t;// 覆盖其余方格chessBoard(tr, tc, tr+s-1, tc+s-1, s);}// 覆盖右上角子棋盘if (dr < tr + s && dc >= tc + s)// 特殊方格在此棋盘中chessBoard(tr, tc+s, dr, dc, s);else {// 此棋盘中无特殊方格// 用t 号L型骨牌覆盖左下角board[tr + s - 1][tc + s] = t;// 覆盖其余方格chessBoard(tr, tc+s, tr+s-1, tc+s, s);}// 覆盖左下角子棋盘if (dr >= tr + s && dc < tc + s)// 特殊方格在此棋盘中chessBoard(tr+s, tc, dr, dc, s);else {// 用t 号L型骨牌覆盖右上角board[tr + s][tc + s - 1] = t;// 覆盖其余方格chessBoard(tr+s, tc, tr+s, tc+s-1, s);}// 覆盖右下角子棋盘if (dr >= tr + s && dc >= tc + s)// 特殊方格在此棋盘中chessBoard(tr+s, tc+s, dr, dc, s);else {// 用t 号L型骨牌覆盖左上角board[tr + s][tc + s] = t;// 覆盖其余方格chessBoard(tr+s, tc+s, tr+s, tc+s, s);}}一、实验目的与要求1、熟悉二分搜索算法;2、初步掌握分治算法;二、实验题1、设a[0:n-1]是一个已排好序的数组。
线性时间选择

应用7:线性时间选择(续)
设所有元素互不相同。在这种情况下, 找出的基准x至少比 3(n-5)/10个元 素大,因为在每一组中有2个元素小 于本组的中位数,而n/5个中位数 中又有(n-5)/10个小于基准x。
同理,基准x也至少比3 (n-5)/10个 元素小。而当n≥75时, 3(n-5)/10 ≥n/4,所以按此基准划分所得的2个 子数组的长度都至少缩短1/4。
T
(n)
C2
n
T
(n
C1 / 5)
T
(3n
/
4)
n 75 n 75
根据定理有:
f (n)
பைடு நூலகம்
c2n 1 1
3
20c2n
(n)
54
因此,T(n)=O(n)。
补充:定理
• 定理:令b, d和c1,c2是大于0的常数,则如下递归
方程
• 的解是:
f
(n
)
b f (floor
(c1n))
f
n 1 (floor(c2n))
for ( int i = 0; i<=(r-p-4)/5; i++ ) 将a[p+5*i]至a[p+5*i+4]的第3小元素 与a[p+i]交换位置;
//找中位数的中位数,r-p-4即上面所说的n-5 Type x = Select(a, p, p+(r-p-4)/5, (r-p-4)/10); int i=Partition(a,p,r, x), j=i-p+1; if (k<=j) return Select(a,p,i,k); else return Select(a,i+1,r,k-j); }
算法设计与分析课件--分治法-线性时间选择

2.5 线性时间选择
这样找到的m*划分是否能达到O(n)的时间复杂度? |A| = |D| = 2r, |B| = |C| = 3r +2,n = 10r +5. |A| + |D| + |C| = 7r + 2 = 7(n-5)/10 +2 = 7n/10 -1.5 < 7n/10 表明子问题的规模不超过原问题的7/10(d)。
T(n) = T(cn) + T(dn) + tn
6
2.5 线性时间选择
Select(S, k) Input: n个数的数组S,正整数k
T(n) = T(cn) + T(dn) + tn
Output: S中的第k个小元素
1. 将S划分成5个元素一组,共[n/5]个组;
2. 每组寻找一个中位数,把这些中位数放到集合M中;
寻找一个分割点m*, 使得左边子表S1中的元素都小于m*, 右子表 S2中的元素都大于m*。 如果寻找m*的时间复杂度达到O(nlogn), 那就不如直接使用排序 算法了。 如果直接寻找m*, 时间复杂度是O(n). 假设选择算法的时间复杂度为T(n), 递归调用这个算法在S的一 个真子集M上寻找m*,应该使用T(cn)时间,这里c是小于1的常数, 反映了M的规模与S相比缩小许多。
✓ 不妨假设n是5的倍数,且n/5是奇数,即n/5 = 2r+1. 于是: |A| = |D| = 2r, |B| = |C| = 3r +2,n = 10r +5.
✓ 如果A和D中的元素都小于m*,那么把它们的元素都加入到S1, S1对应规约后子问题的上限。 类似的,若A和D中的元素都 大于m*, 则把他们的元素都加 入到S2,S2对应规约后子问题 的上限。
快速选择算法线性时间选择第k小的元素

快速选择算法线性时间选择第k小的元素快速选择算法:线性时间选择第k小的元素快速选择算法是一种高效的算法,用于在未排序的数组中选择第k 小的元素。
该算法的时间复杂度为O(n),在大规模数据处理和排序任务中具有广泛的应用。
1. 算法原理快速选择算法基于快速排序算法的分治思想,通过每次选择一个枢纽元素,并将数组中的元素分为左右两部分,来实现快速查找排序后的第k小元素。
具体步骤如下:- 选择枢纽元素:从未排序数组中选择一个元素作为枢纽元素,可以随机选择或选择固定位置的元素,比如选取数组的第一个元素。
- 划分数组:将数组分为两部分,左边的元素小于枢纽元素,右边的元素大于等于枢纽元素。
- 判断位置:比较枢纽元素的位置与k的大小关系,如果位置小于k,则递归在右半部分查找第k小元素;如果位置大于k,则递归在左半部分查找第k小元素;否则,返回该位置的元素即为第k小元素。
2. 算法步骤下面给出一种实现快速选择算法的伪代码:```function quickSelect(A, k, left, right):if left == right:return A[left]pivotIndex = partition(A, left, right)if k == pivotIndex:return A[k]else if k < pivotIndex:return quickSelect(A, k, left, pivotIndex - 1) else:return quickSelect(A, k, pivotIndex + 1, right) function partition(A, left, right):pivot = A[left]i = left + 1j = rightwhile i <= j:if A[i] < pivot and A[j] > pivot:swap A[i] and A[j]i = i + 1j = j - 1if A[i] >= pivot:i = i + 1if A[j] <= pivot:j = j - 1swap A[left] and A[j]return j```3. 算法性能分析快速选择算法通过每次划分数组来减小搜索范围,因此平均时间复杂度为O(n),其中n为数组的长度。
算法设计与分析线性时间排序ppt课件

快速排序算法Βιβλιοθήκη 不稳定归并排序算法
稳定
直接插入排序算法 稳定
冒泡排序算法
稳定
计数排序算法
稳定
桶排序算法
稳定
程序演示及阐明
(程序演示及阐明)
作业
思索题9-2:以线性时间作原地置换排序
The End
Thank you!
桶排序算法
桶排序分析
正确性:反证法 时间代价:
桶排序分析
排序算法稳定性
假设待排序的序列中,存在多个具有一 样值的元素,经过排序,这些元素的相 对次序坚持不变,那么称该算法是稳定 的;假设经排序后,元素的相对 次序发 生了改动,那么称该算法是不稳定的。
常见排序算法的稳定性
堆排序算法
不稳定
1 for i ← 1 to d
2 do 运用一种稳定的排序方法来对
数组A按第i位数字进展排序
基数排序分析
正确性:归纳证明 时间代价: 当每位数字都介于1-k之间,且k不太大时,
可以选择计数排序。 每一位上的处置时间为: (n+k) 总时间为: (d(n+k)), 当d为常量,
k= (n)时, (d(n+k))= (n)
算法设计与分析
谭守标 安徽大学 电子学院
2019.9
第七章 线性时间排序
排序算法的下界 计数排序〔过程及分析〕 基数排序 桶排序〔过程及分析〕 程序演示及阐明
排序算法的下界
决策树 最坏情况下界 定理9.1 推论9.2
决策树
决策树表示了某种排序算法作用于给定输入 上所做的一切比较,而控制构造,数据挪动等那 么被忽略。
计数排序思绪 计数排序算法 计数排序分析
计数排序思绪
算法:线性时间选择(CC++)

算法:线性时间选择(CC++)Description给定线性序集中n个元素和⼀个整数k,n<=2000000,1<=k<=n,要求找出这n个元素中第k⼩的数。
Input第⼀⾏有两个正整数n,k. 接下来是n个整数(0<=ai<=1e9)。
Output输出第k⼩的数Sample Input6 31 3 52 4 6Sample Output3利⽤快速排序可以找出第k⼩的,加上随机函数改进⼀下:#include <cstdio>#include <cstdlib>#include <ctime>#include <iostream>int num[2000001];void quictSort(int, int, int);int partition(int, int);int main(){int n, m, i;srand(unsigned(time(NULL))); // 随机函数种⼦while (~scanf("%d%d", &n, &m)){for (i = 0; i < n; i++)scanf("%d", &num[i]);quictSort(0, n - 1, m - 1);printf("%d\n", num[m - 1]);}return 0;}// 快速排序void quictSort(int left, int right, int mTop){if (left < right){int p = partition(left, right); // 分为两段if (p == mTop) // 如果随机找到第mTop⼩就直接返回return;if (p < mTop)quictSort(p + 1, right, mTop); // 找到的位置⽐mTop⼩就在[p + 1, right]区间找if (p > mTop)quictSort(left, p - 1, mTop); // 找到的位置⽐mTop⼤就在[left, p - 1]区间找}}// 从⼩到⼤排int partition(int left, int right){int r = rand() % (right - left + 1) + left; // 随机选择⼀个数int key = num[r];std::swap(num[r], num[left]); // 交换到数组⾸位while (left < right){// 从数组后⾯开始, 找⽐随机选择的数⼩的, 然后从前找⽐随机选择的数⼤的while (left < right && num[right] >= key)right--;if (left < right)num[left] = num[right];while (left < right && num[left] <= key)left++;if (left < right)num[right] = num[left];}num[left] = key; // 将随机选择的数存回return left; // 返回随机选择的数分割数组的下标, 左边都是⽐它⼩的, 右边都是⽐它⼤的}中位数法线性时间选择划分:AC代码:#include <cstdio>#include <cstdlib>int num[2000001];int select(int low, int high, int top);int partition(int low, int high, int median); void selectSort(int low, int high);void swap(int &a, int &b);int main(){int n, m, i;while (~scanf("%d%d", &n, &m)){for (i = 0; i < n; i++)scanf("%d", &num[i]);printf("%d\n", select(0, n - 1, m - 1));/*for (i = 0; i < n; i++)printf("%d%c", num[i], i < n - 1 ? ' ' : '\n'); */}return 0;}// 中位数法线性时间选择int select(int low, int high, int top){// ⼩于75个数据随便⽤⼀个排序⽅法if (high - low < 74){selectSort(low, high); // 选择排序return num[low + top]; // 排完序直接返回第low + top的数}int groupNum = (high - low - 4) / 5; // 每组5个数, 计算多少个组, 从0开始计数for (int i = 0; i <= groupNum; i++){int start = low + 5 * i; // 每组的起始位置int end = start + 4; // 每组的结束位置for (int j = 0; j < 3; j++) // 从⼩到⼤冒3个泡for (int k = start; k < end - j; k++)if (num[k] > num[k + 1])swap(num[k], num[k+1]);swap(num[low + i], num[start + 2]); // 每组的中位数交换到前⾯第low + i的位置}// 上⾯排完后, 数组low + 0 到 low + groupNum都是每⼀组的中位数int median = select(low, low + groupNum, (groupNum + 1) / 2); // 找中位数的中位数int p = partition(low, high, median); // 将数组分为两段, 左边的⼩于中位数的中位数, 右边的⼤于中位数的中位数 int n = p - low; // 计算p到low之间有多少个数, 后⾯得减掉if (n == top)return num[p]; // 如果运⽓好, 刚好要找的就是中位数if (n > top)return select(low, p - 1, top); // n⽐top⼤就在左边找if (n < top)return select(p + 1, high, top - n - 1); // n⽐top⼩就在右边找, 并且top要减去已经⼤的个数}// 以中位数进⾏分割, 分成两半int partition(int low, int high, int median){int p;for (int i = low; i <= high; i++)if (num[i] == median){p = i;break;}// 将中位数交换到最前⾯swap(num[p], num[low]);// 记下最前⾯的数int key = num[low];// 把⼩于key的放前⾯, ⼤于key的放后⾯while (low < high){while (num[high] >= key && low < high)high--;if (low < high)num[low] = num[high];while (num[low] <= key && low < high)low++;if (low < high)num[high] = num[low];}// 分别从两头开始, 找到中间时, 把key存回num[low] = key;return low;}// 选择排序void selectSort(int low, int high){for (int i = low; i <= high; i++){int MIN = i;for (int j = i + 1; j <= high; j++)if (num[MIN] > num[j])MIN = j;swap(num[i], num[MIN]);}}// 交换两个元素void swap(int &a, int &b){int temp = a;a = b;b = temp;}。
线性时间选择

线性时间选择I.问题描述给定线性序集中n个元素和一个整数k,1≤k≤n,要求找出这n个元素中第k小的元素,即如果将这n个元素依其线性序排列时,排在第k个位置的元素即为要找的元素。
当k=1时,就是要找的最小元素;当k=n时,就是要找最大元素;当k=(n+1)/2时,称为找中位数。
II.问题分析在线性序集n个元素中找出第k小的元素,可以采用分治策略的思想。
模仿前面的随机选择策略的快速排序算法,对输入的数组进行递归划分。
与快速排序算法不同的是,它只对划分的子数组之一进行递归处理。
在算法RandomizedSelect中执行Randomized_Partition后,数组a[p:r]被划分成两个子数组a[p:i]和a[i+1:r],使a[p:i]中每个元素都不大于a[i+1:r]中每个元素。
接着算法计算子数组a[p:i]中元素个数j。
如果k≤j,则a[p:r]中第k小元素落在子数组a[p:i]中。
如果k>j,则要找的第k小元素落在子数组a[i+1:r]中。
由于此时已知道子数组a[p:i]中元素均小于要找的第k小元素,因此,要找的a[p:r]中第k小元素是a[i+1:r]中的第k-j小元素。
算法复杂性分析:容易看出,在最坏情况下,算法RandomizedSelect需要O(n^2)计算时间,例如,在找最小元素时,总是在最大元素处划分。
但是,该算法的平均时间复杂度为O(n)。
III.算法描述RandomizedSelect(A,p,r,i)//找出第k小元素函数if p==r //数组中只有一个数return A[p]q=Randomized_Partition(A,p,r)// 调用随机划分函数,即同前面的随机选择策略的快速排序k=q-p+1if i==kreturn A[q]else if i<kreturn RandomizedSelect(A,p,q-1,i) //在左半段找第k小元素else return RandomizedSelect(A,q+1,r,i-k) //在右半段找第k小元素Randomized_Partition(A,p,r) //随机划分函数i=Random(p,r)exchange A[r] with A[i]return Partition(A,p,r)Partition(A,p,r)//快速排序函数x=A[r]i=p-1for j=p to r-1if A[j]≤xi=i+1exchange A[i] with A[j]exchange A[i+1] with A[r]return i+1IV.程序用C++描述如下:#include <iostream>using namespace std;int RandomizedSelect(int array[], int begin, int end, int rank);int Randomized_Partition(int a[],int p,int r);void Randomized_QuickSort(int a[],int p,int r);int Partition(int a[],int p,int r);void Swap(int &a,int &b);int RandomizedSelect(int array[], int begin, int end, int rank) //找出第k小元素函数{if (begin == end){return array[begin];}//随机选取一个基准元素,将数组按照基准元素值的大小分区,//基准元素的左侧都是比基准元素小的元素//基准元素的右侧都是比基准元素大的元素//返回分区后的基准元素的数组索引int q = Randomized_Partition(array, begin, end);//计算基准元素的数组排位int k = q - begin + 1;if (rank == k){//分区的基准元素刚好是排在rank位置上, 则直接返回基准元素return array[q];}else if (rank < k){//分区的基准元素比rank大,转为在基准元素左面的区间中寻找return RandomizedSelect(array, begin, q - 1, rank);}else{//分区的基准元素比rank小,转为在基准元素右面的区间中寻找return RandomizedSelect(array, q + 1, end, rank - k);}}//实现随机功能的函数int Random(int p,int r){return rand()%(r-p+1)+p;}//随机划分函数int Randomized_Partition(int a[],int p,int r){//随机的从p至r中抽取一个数int i=Random(p,r);//将a[i]和a[p]交换Swap(a[i],a[p]);//调用划分函数return Partition(a,p,r);}//用于划分左右数组的函数//p为数组下界,r为上界int Partition(int a[],int p,int r){int i=p,j=r+1;int x=a[p];//将小于x的元素交换到左边区域//将大于x的元素交换到右边区域while(true){while((a[++i]<x)&&(i<r));while(a[--j]>x);if(i>=j) break;Swap(a[i],a[j]);}a[p]=a[j];a[j]=x;return j;}//用于实现数组成员交换的函数void Swap(int &a,int &b){int c;c=a;a=b;b=c;}void main(){int n,r,k;cout<<"线性时间选择"<<endl<<"请输入数组规模:";cin>>n;int *a=new int[n];cout<<"输入要排序的数:"<<endl;for(int i=0;i<n;i++)cin>>a[i]; //输入待排序数组cout<<"请输入要找的第k小元素:"<<endl;cin>>k;r=RandomizedSelect(a,0,n-1,k); //求第k小元素cout<<"第k小元素为:"<<r<<endl;cout<<endl<<"END"<<endl;}。
《算法设计与分析》实验指导书

《算法设计与分析》实验指导书《算法设计与分析》实验指导书本文档主要用于《算法设计与分析》课程的实验指导。
《算法设计与分析》旨在教会学生处理各种问题的方法,通过实验,使学生能够把所学的方法用于具体的问题,并对所用算法进行比较分析,从而提高学生分析问题、解决问题的能力。
通过该课程的实验,使学生对课堂中所讲述的内容有一个直观的认识,更好地掌握所学的知识,培养学生的实际动手能力,加强学生创新思维能力的培养。
本课程设计了7个设计型实验。
实验内容包括用分治法、动态规划、贪心法、回溯法以及分支限界法求解问题。
一、实验内容安排二、实验基本要求实验前要求学生一定要先了解实验目的、内容、要求以及注意事项,要求学生熟悉实验对象,设计并编写相应的算法。
学生应独立完成所布置实验内容,编写代码,运行程序,记录结果并撰写实验报告。
三、实验报告要求实验结束后,应及时整理出实验报告,实验报告提交书面文档。
四、考核方式理论考试(60%)+实验(30%)+作业(10%)五、实验内容与指导实验一快速排序问题1.实验目的(1) 用分治法求解该问题。
2.实验环境PC机,要求安装Eclipse软件或VC++软件供学生实验。
3.实验内容有n个无序的数值数据,现要求将其排列成一个有序的序列。
4. 实验步骤(1) 输入实现该问题的源代码;(2) 输入测试数据,验证代码的正确性。
5.实验要求(1)做好实验预习,熟悉本实验中所使用的开发环境。
(2)写出实验报告①实验目的②实验内容③出错信息及处理方法④实验结果实验二最少硬币问题1.实验目的(1) 用动态规划求解该问题。
2.实验环境PC机,要求安装Eclipse软件或VC++软件供学生实验。
3.实验内容有n种不同面值的硬币,各硬币面值存于数组T[1:n];现用这些面值的钱来找钱;各面值的个数存在数组Num[1:n]中。
对于给定的1≤n≤10,硬币面值数组、各面值的个数及钱数m,0<=m<=2001,设计一个算法,计算找钱m的最少硬币数。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
《线性时间选择》讲解文档
问题:
给定线性序集中n个元素和一个整数k,1≤k≤n,要求找出这n个元素中第k小的元素
基本思想:
template<class Type>
Type RandomizedSelect(Type a[],int p,int r,int k)
{
if (p==r) return a[p];
int i=RandomizedPartition(a,p,r),
j=i-p+1;
if (k<=j) return RandomizedSelect(a,p,i,k);
else return RandomizedSelect(a,i+1,r,k-j);
}
分析:
在最坏情况下,算法randomizedSelect需要O(n2)计算时间
但可以证明,算法randomizedSelect可以在O(n)平均时间内找出n个输入元素中的第k小元素。
改进算法:【中位数】
如果能在线性时间内找到一个划分基准,使得按这个基准所划分出的2个子数组的长度都至少为原数组长度的ε倍(0<ε<1是某个正常数),那么就可以在最坏情况下用O(n)时间完成选择任务。
例如,若ε=9/10,算法递归调用所产生的子数组的长度至少缩短1/10。
在最坏情况下,算法所需的计算时间T(n)满足递归式T(n)≤T(9n/10)+O(n) 。
由此可得T(n)=O(n)。
具体步骤:
将n个输入元素划分成 n/5 个组,每组5个元素,只可能有一个组不是5个元素。
用任意一种排序算法,将每组中的元素排好序,并取出每组的中位数,共 n/5 个。
递归调用select来找出这 n/5 个元素的中位数。
如果 n/5 是偶数,就找它的2个中位数中较大的一个。
以这个元素作为划分基准
设所有元素互不相同。
在这种情况下,找出的基准x至少比3(n-5)/10个元素大,因为在每一组中有2个元素小于本组的中位数,而n/5个中位数中又有(n-5)/10个小于基准x。
同理,基准x也至少比3(n-5)/10个元素小。
而当n≥75时,3(n-5)/10≥n/4所以按此基准划分所得的2个子数组的长度都至少缩短1/4。
具体算法:
Type Select(Type a[], int p, int r, int k)
{
if (r-p<75) {
用某个简单排序算法对数组a[p:r]排序;
return a[p+k-1];
};
for ( int i = 0; i<=(r-p-4)/5; i++ )
将a[p+5*i]至a[p+5*i+4]的第3小元素与a[p+i]交换位置;
//找中位数的中位数,r-p-4即上面所说的n-5
Type x = Select(a, p, p+(r-p-4)/5, (r-p-4)/10);
int i=Partition(a,p,r, x),
j=i-p+1;
if (k<=j) return Select(a,p,i,k);
else return Select(a,i+1,r,k-j);
}
上述算法将每一组的大小定为5,并选取75作为是否作递归调用的分界点。
这2点保证了T(n)的递归式中2个自变量之和n/5+3n/4=19n/20=εn,0<ε<1。
这是使T(n)=O(n)的关键之处。
当然,除了5和75之外,还有其他选择。
复杂度分析
T(n)=O(n)
运行结果:。