线性时间选择算法实现

void swap(int *a,int *b);
//主函数
int main()
{
int *a,cnt,i,k,result;
FILE *fp;
//clrscr();
printf("Input the count of elements:");
scanf("%d",&cnt);
printf("Choose the element :");
{
int i=p,j=r+1;
while(1)
{
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 sort(int *a,int p,int r)
}
for(i=0;i<cnt;i++)
{
a[i]=rand()%cnt+100;
fprintf(fp,"%4d\n",a[i]);
}
result=select(a,0,cnt-1,k);
printf("The result is:%d",result);
fclose(fp);
free(a);
return 0;
if(k<=j) //比较k和j来确定在数组哪一部分继续选择
return select(a,p,i,k);
else
return select(a,i+1,r,k-j);
}
int partition(int *a,int p,int r,int x)
//以x为基准,将a[p...r]分割成两部分,并返回x的下标。
【题目】:给定线性序集中n个元素和一个整数k,1≤k≤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)。
{
sort(a,p+5*i,p+5*i+4);
swap(&a[p+5*i+2],&a[p+i]);
}
temp=select(a,p,p+(r-p-4)/5,(r-p-4)/10);//找中位数的中位数为划分基准
i=partition(a,p,r,temp); //依照基准划分原数组,并返回基准下标
j=i-p+1; //基准下标为a[p.....r]的第几个元素,与k的形式相同
//对a[p...r]进行冒泡排序
{
int i,j,temp;
for(i=p;i<r;i++)
{
for(j=r;j>i;j--) //此处r为下标,j的范围应该最大为r-1
if(a[j-1]>a[j])
{
temp=a[j-1];
a[j-1]=a[j];
a[j]=t}
void swap(int *a,int *b)
#include<stdio.h>
#include<stdlib.h>
#include<malloc.h>
#include<time.h>
int select(int *a,int p,int r,int k);
int partition(int *a,int p,int r,int x);
void sort(int *a,int p,int r);
scanf("%d",&k);
a=(int *)malloc(cnt*sizeof(int));
srand(time(NULL));
if((fp=fopen("d:\\output.txt","w+"))==NULL)
{
printf("Cannot open this file!");
exit(0);
{
int temp;
temp=*a;
*a=*b;
*b=temp;
}
}
int select(int *a,int p,int r,int k) //程序核心部分
{
char filename[10];
int i,j,temp;
if(r-p<75) //数组元素小于75个的时候,用简单排序法进行排序
{
sort(a,p,r);
return a[p+k-1];
}
for(i=0;i<(r-p-4)/5;i++) //将cnt个元素每5个元素分成一组,分别排序,并将该组中位数与a[p+i]交换位置。循环执行完后,所有组的中位数集中到数组前a[0....(r-p-4)/5-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); }

算法设计与分析线性时间选择

算法设计与分析线性时间选择

福州大学数学与计算机科学学院)《计算机算法设计与分析》上机实验报告(1(1)将所有的数n个以每5个划分为一组共组,将不足5个的那组忽略,然后用任意一种排序算法,因为只对5个数进行排序,所以任取一种排序法就可以了。

将每组中的元素排好序再分别取每组的中位数,得到个中位数。

.(2)取这个中位数的中位数,如果是偶数,就找它的2个中位数中较大的一个作为划分基准。

(3)将全部的数划分为两个部分,小于基准的在左边,大于等于基准的放右边。

在这种情况下找出的基准x至少比个元素大。

因为在每一组中有2个元素小于本组的中位数,有个小于基准,中个中位数中又有即位数处于,个小于基准x。

因此至少有个元素小于基准x。

同理基准x也至少比个元素小。

而当n≥75时≥n/4所以按此基准划分所得的2个子数组的长度都至少缩短1/4。

通过上述说明可以证明将原问题分解为两个子问题进行求解能够更加节省求解时间。

3.查找中位数程序代码1.椣据畬敤尠瑳慤硦栮2.#include <ctime>3.#include <iostream>ing namespace std;5.6.template <class Type>7.void Swap(Type &x,Type &y);8.9.inline int Random(int x, int y);10.11.template <class Type>12.void BubbleSort(Type a[],int p,int r);13.14.template <class Type>15.int Partition(Type a[],int p,int r,Type x);16.17.template <class Type>18.Type Select(Type a[],int p,int r,int k);19.20.int main()21.{22.//初始化数组23.int a[200];24.25.//必须放在循环体外面26. srand((unsigned)time(0));27.28.for(int i=0; i<200; i++)29. {30. a[i] = Random(0,500);31. cout<<慜屛<<i<<嵜尺<<a[i]<<?;32. }33. cout<<endl;34.35. cout<<第100小的元素是<<Select(a,0,199,100)<<endl;36.37.//重新排序,对比结果38. BubbleSort(a,0,199);39.40.for(int i=0; i<200; i++)41. {42. cout<<慜屛<<i<<嵜尺<<a[i]<<?;43. }44. cout<<endl;45.}46.47.template <class Type>48.void Swap(Type &x,Type &y)49.{50. Type temp = x;51. x = y;52. y = temp;53.}54.55.inline int Random(int x, int y)56.{57.int ran_num = rand() % (y - x) + x;58.return ran_num;59.}60.61.//冒泡排序62.template <class Type>63.void BubbleSort(Type a[],int p,int r)64.{65.//记录一次遍历中是否有元素的交换66.bool exchange;67.for(int i=p; i<=r-1;i++)68. {69. exchange = false ;70.for(int j=i+1; j<=r; j++)71. {72.if(a[j]<a[j-1])73. {74. Swap(a[j],a[j-1]);75. exchange = true;76. }77. }78.//如果这次遍历没有元素的交换,那么排序结束79.if(false == exchange)80. {81.break ;82. }83. }84.}85.86.template <class Type>87.int Partition(Type a[],int p,int r,Type x)88.{89.int i = p-1,j = r + 1;90.91.while(true)92. {93.while(a[++i]<x && i<r);94.while(a[--j]>x);95.if(i>=j)96. {97.break;98. }99. Swap(a[i],a[j]);100. }101.return j;102.}103.104.105.template <class Type>106.Type Select(Type a[],int p,int r,int k) 107.{108.if(r-p<75)109. {110. BubbleSort(a,p,r);111.return a[p+k-1];112. }113.//(r-p-4)/5相当于n-5114.for(int i=0; i<=(r-p-4)/5; i++)115. {116.//将元素每5个分成一组,分别排序,并将该组中位数与a[p+i]交换位置117.//使所有中位数都排列在数组最左侧,以便进一步查找中位数的中位数118. BubbleSort(a,p+5*i,p+5*i+4);119. Swap(a[p+5*i+2],a[p+i]);120. }121.//找中位数的中位数122. Type x = Select(a,p,p+(r-p-4)/5,(r-p-4)/10);123.int i = Partition(a,p,r,x);124.int j = i-p+1;125.if(k<=j)126. {127.return Select(a,p,i,k);128. }129.else130. {131.return Select(a,i+1,r,k-j);132. }133.}4.时间复杂性分析设对n个元素的数组调用Select需要T(n)时间,那么找中位数的中位数x至多用T(n/5)时间。

线性时间选择中位数

线性时间选择中位数

湖南涉外经济学院计算机科学与技术专业《算法设计与分析》课程线性时间选择(中位数)实验报告班级:学号:姓名:教师:成绩:2012年5月【实验目的】1 掌握线性时间选择的基本算法及其应用2 利用线性时间选择算法找出数组的第k小的数3 分析实验结果,总结算法的时间和空间复杂度【系统环境】Windows7 旗舰版平台【实验工具】VC++6.0英文企业版【问题描述】描述:随机生成一个长度为n的数组。

数组为随机生成,k由用户输入。

在随机生成的自然数数组元素找出这n个数的第k小的元素。

例:A[5]={3,20,50,10,21} k=3,则在数组A中第3小的元素为20【实验原理】原理:将所有的数(n个),以每5个划分为一组,共[n/5]组(将不足五个的那组忽略);然后用任意一种排序算法(因为只对五个数进行排序,所以任取一种排序法就可以了,这里我选用冒泡排序),将每组中的元素排好序再分别取每组的中位数,得到[n/5]个中位数;再取这[n/5]个中位数的中位数(如果n/5是偶数,就找它的2个中位数中较大的一个)作为划分基准,将全部的数划分为两个部分,小于基准的在左边,大于等于基准的放右边。

在这种情况下,找出的基准x至少比3(n-5)/10个元素大,因为在每一组中有2个元素小于本组的中位数,中位数处于1/2*[n/5-1],即n/5 个中位数中又有(n-5)/10个小于基准x。

同理,基准x也至少比3(n-5)/10个元素小。

而当n≥75时,3(n-5)/10≥n/4所以按此基准划分所得的2个子数组的长度都至少缩短1/4。

思路:如果能在线性时间内找到一个划分基准,使得按这个基准所划分出的2个子数组的长度都至少为原数组长度的ε倍(0<ε<1是某个正常数),那么就可以在最坏情况下用O(n)时间完成选择任务。

例如:若ε=9/10,算法递归调用所产生的子数组的长度至少缩短1/10。

所以,在最坏情况下,算法所需的计算时间T(n)满足递归式T(n)≤T(9n/10)+O(n) 。

线性时间选择实验报告

线性时间选择实验报告

一、实验目的本次实验旨在掌握线性时间选择算法的基本原理,通过实现该算法,解决在未排序数组中查找第k小的元素的问题,并分析算法的时间和空间复杂度。

二、实验环境1. 操作系统:Windows 102. 编程语言:C++3. 开发工具:Visual Studio 2019三、实验原理线性时间选择算法是一种高效的算法,能够在O(n)时间复杂度内找到未排序数组中第k小的元素。

该算法基于快速选择(Quickselect)算法,通过随机划分和递归的方式实现。

算法步骤如下:1. 随机选择一个元素作为基准(pivot)。

2. 将数组划分为两部分,小于基准的元素放在基准的左侧,大于基准的元素放在基准的右侧。

3. 根据k的值,判断第k小的元素在哪个子数组中:a. 如果k小于等于左子数组的长度,则在左子数组中递归查找第k小的元素。

b. 如果k大于左子数组的长度且小于左子数组的长度加1,则基准元素即为第k小的元素。

c. 如果k大于左子数组的长度加1,则在右子数组中递归查找第k小的元素。

4. 重复步骤1-3,直到找到第k小的元素。

四、实验过程1. 设计线性时间选择算法的C++实现。

2. 编写主函数,输入数组元素和k的值。

3. 调用线性时间选择算法函数,输出第k小的元素。

五、实验结果与分析1. 实验数据给定一个未排序的数组:2, 9, 11, 3, 14, 7, 10, 8, 15, 4, 13, 1, 6, 5, 12。

要求找到第k小的元素,其中k的值为8。

2. 实验结果通过线性时间选择算法,找到第8小的元素为7。

3. 算法复杂度分析- 时间复杂度:平均情况下,线性时间选择算法的时间复杂度为O(n),最坏情况下为O(n^2)。

但在实际应用中,通过随机化选择基准,可以保证算法的时间复杂度接近O(n)。

- 空间复杂度:线性时间选择算法的空间复杂度为O(1),因为它在原数组上进行操作,不需要额外的存储空间。

六、实验总结本次实验成功实现了线性时间选择算法,并验证了其在实际应用中的高效性。

算法设计与分析课件--分治法-线性时间选择

算法设计与分析课件--分治法-线性时间选择
9
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对应规约后子问题 的上限。

线 性 规 划 算 法 详 解

线 性 规 划 算 法 详 解

Java基础算法详解查找和排序算法是算法的入门知识,其经典思想可以用于很多算法当中。

因为其实现代码较短,应用较常见。

所以在面试中经常会问到排序算法及其相关的问题。

但万变不离其宗,只要熟悉了思想,灵活运用也不是难事。

一般在面试中最常考的是快速排序和归并排序,并且经常有面试官要求现场写出这两种排序的代码。

对这两种排序的代码一定要信手拈来才行。

还有插入排序、冒泡排序、堆排序、基数排序、桶排序等。

面试官对于这些排序可能会要求比较各自的优劣、各种算法的思想及其使用场景。

还有要会分析算法的时间和空间复杂度。

通常查找和排序算法的考察是面试的开始,如果这些问题回答不好,估计面试官都没有继续面试下去的兴趣都没了。

所以想开个好头就要把常见的排序算法思想及其特点要熟练掌握,有必要时要熟练写出代码。

冒泡排序冒泡排序是最简单的排序之一了,其大体思想就是通过与相邻元素的比较和交换来把小的数交换到最前面。

这个过程类似于水泡向上升一样,因此而得名。

举个栗子,对5,3,8,6,4这个无序序列进行冒泡排序。

首先从后向前冒泡,4和6比较,把4交换到前面,序列变成5,3,8,4,6。

同理4和8交换,变成5,3,4,8,6,3和4无需交换。

5和3交换,变成3,5,4,8,6,3.这样一次冒泡就完了,把最小的数3排到最前面了。

对剩下的序列依次冒泡就会得到一个有序序列。

冒泡排序的时间复杂度为O(n^2)。

实现代码:*@Description:冒泡排序算法实现public class BubbleSort {public static void bubbleSort(int[] arr) {if(arr == null || arr.length == 0)for(int i=0; i) {for(int j=arr.length-1; ji; j--) {if(arr[j]arr[j-1]) {swap(arr, j-1, j);public static void swap(int[] arr, int i, int j) { int temp = arr[i];arr[i] = arr[j];arr[j] = temp;抑或简单理解一点的正向排序public class BubbleSort {public static void bubbleSort(int[] arr) {if(arr == null || arr.length == 0)for(int i=1;iarr.length-1;i++) {for(int j=0; jarr.length-i; j++) {if(arr[j]arr[j+1]) {swap(arr, j+1, j);public static void swap(int[] arr, int i, int j) {int temp = arr[i];arr[i] = arr[j];arr[j] = temp;选择排序选择排序的思想其实和冒泡排序有点类似,都是在一次排序后把最小的元素放到最前面。

快速选择算法线性时间选择第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为数组的长度。

C语言中的搜索算法详解

C语言中的搜索算法详解搜索算法在计算机科学中起着重要的作用,它们可以帮助我们在大量数据中迅速找到目标元素。

在C语言中,有多种搜索算法可供选择。

本文将深入探讨一些常用的搜索算法,包括线性搜索、二分搜索和哈希表搜索。

一、线性搜索线性搜索是最简单的搜索算法之一,也被称为顺序搜索。

它逐个比较列表中的元素,直到找到目标元素或搜索完整个列表。

这种算法适用于无序列表,并且其时间复杂度为O(n),其中n为列表的长度。

在C语言中,我们可以使用for循环来实现线性搜索算法。

下面是一个示例代码:```c#include <stdio.h>int linear_search(int arr[], int n, int target) {for(int i = 0; i < n; i++) {if(arr[i] == target) {return i;}}return -1;}int main() {int arr[] = {1, 2, 3, 4, 5};int n = sizeof(arr) / sizeof(arr[0]);int target = 3;int result = linear_search(arr, n, target);if(result != -1) {printf("目标元素在列表中的索引为:%d\n", result);} else {printf("目标元素不在列表中。

\n");}return 0;}```二、二分搜索二分搜索是一种更有效的搜索算法,前提是列表已经按照升序或降序排列。

它通过将目标元素与列表的中间元素进行比较,并根据比较结果将搜索范围缩小一半。

这种算法的时间复杂度为O(logn),其中n 为列表的长度。

在C语言中,我们可以使用递归或迭代的方式实现二分搜索算法。

下面是一个使用迭代方式实现的示例代码:```c#include <stdio.h>int binary_search(int arr[], int low, int high, int target) {while(low <= high) {int mid = (low + high) / 2;if(arr[mid] == target) {return mid;} else if(arr[mid] < target) {low = mid + 1;} else {high = mid - 1;}}return -1;}int main() {int arr[] = {1, 2, 3, 4, 5};int n = sizeof(arr) / sizeof(arr[0]);int target = 3;int result = binary_search(arr, 0, n - 1, target);if(result != -1) {printf("目标元素在列表中的索引为:%d\n", result);} else {printf("目标元素不在列表中。

线性规划问题的算法综述

线性规划问题的算法综述本文从网络收集而来,上传到平台为了帮到更多的人,如果您需要使用本文档,请点击下载按钮下载本文档(有偿下载),另外祝您生活愉快,工作顺利,万事如意!线性规划概念是在1947年的军事行动计划有关实践中产生的,而相关问题1823年Forier和口1911年PQusi就已经提出过,发展至今已有将近100年的历史了。

现在已成为生产制造、市场营销、银行贷款、股票行情、出租车费、统筹运输、电话资费、电脑上网等等热点现实问题决策的依据。

线性规划就是在满足线性约束下,求线性函数的极值。

毋庸置疑,数学规划领域的重大突破总是始于线形规划。

提到线性规划算法,人们最先想到的是单纯形法和内点法。

单纯形法是实际应用中使用最普遍的一种线性规划算法,而研究者们已证明在最坏的情况下单纯形法的计算复杂度是指数级的,内点算法的计算复杂度是多项式时间的。

把两种算法相提并论,要么是这两种算法都已经非常完备,要么都有需改进之处。

显然不属于前者,即两者都有需要改进之处。

几十年来,研究者通过不断努力,在两种算法的计算上都取得相当的进展。

1数学模型线性规划问题通常表示成如下两种形式:标准型、规范型。

设jj(2…,n)是待确定的非负的决策变量;认2…,n)是与决策变量相对应的价格系数;K2…mj=l2…n)是技术系数;b(i12…,m)是右端项系数;线性规划是运筹学最基本、运用最广泛的分支,是其他运筹学问题研究的基础。

在20世纪50年代到60年代期间,运筹学领域出现许多新的分支:非线性规划(nonlinearprogranming、商业应用(crnxmereialpplieation、大尺度方法(laresealemeh-Qd)随机规划(stochasticPKgiamniig)、整数规划(ntegerprogramming)、互补转轴理论(amplmentaiyPivotheor)多项式时间算法(polynomialtjneagatm)等。

算法:线性时间选择(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;}。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
相关文档
最新文档