第二章实验报告
实践题目名称:找第k小的数
1.问题描述:
设计一个平均时间为O(n)的算法,在n(1<=n<=1000)个无序的整数中找出第k小的数。
提示:函数int partition(int a[],int left,int right)的功能是根据a[left]~a[right]中的某个元素x(如a[left])对a[left]~a[right]进行划分,划分后的x所在位置的左段全小于等于x,右段全大于等于x,同时利用x所在的位置还可以计算出x是这批数据按升非降序排列的第几个数。因此可以编制int find(int a[],int left,int right,int k)函数,通过调用partition函数获得划分点,判断划分点是否第k小,若不是,递归调用find函数继续在左段或右段查找。
输入格式:
输入有两行:
第一行是n和k,0<k<=n<=10000
第二行是n个整数
输出格式:
输出第k小的数
输入样例:
在这里给出一组输入。例如:
10 4
2 8 9 0 1 3 6 7 8 2
输出样例:
在这里给出相应的输出。例如:
2
算法描述:
题设提示使用快速排序,在总共有x个数的时候,每层递归时所选取的参照数在该层递归排序完后,其必定位于次数列第y个空间,前面y-1个数都比它小,后面x-y个数都大于它,即为它即是该数列中第y小的数。因此只需在快速排序的过程中找到在排序后位于第k个空间的参照数,这个数即为我们所要求的第k小的数。
1 #include<bits/stdc++.h>
2 using namespace std;
3
4 int partition(int a[],int left,int right){
5 int l=left,r=right+1;
6 int x=a[left],s;
7 while(l<r){
8 while(a[++l]<x&&l<r);
9 while(a[--r]>x);
10 if(l>=r)break;
11 swap(a[l],a[r]);
12 }
13 a[left]=a[r];
14 a[r]=x;
15 return r;
16 }
17
18 int find(int a[],int left,int right,int k){
19 if(left<=right){
20 int m=partition(a,left,right);
21 if(m==k)return a[m];
22 if(m>k){
23 find(a,left,m-1,k);
24 }
25 else find(a,m+1,right,k);
26 }
27 }
28
29 int main(){
30 int n,k,a[10002];
31 cin >> n >> k;
32 for(int i=1;i<=n;i++){
33 cin >> a[i];
34 }
35 int result = find(a,1,n,k);
36 cout << result;
37 return 0;
38 }
2.算法时间及空间复杂度分析(要有分析过程):
设算法的复杂度为T(N),
第一步分解为两个子问题为O(1)
第二步分别求解两个子问题为O(N/2)*2
第三步合并子问题为O(N)
等式为:T(N)=O(1)+2T(N/2)+O(N)
得:T(N)=O(nlogn);
心得体会(对本次实践收获及疑惑进行总结)
实验的目的是运用快速排序算法进行第k小的数的查找,虽然运用快速排序算法的思想,但却并不完全相同,能够帮助我们复习掌握快速排序算法的同时,又发现学习到一些新的东西,举一反三。