算法第二章上机实验报告

实践题目

   2-1 找第k小的数 

问题描述  

设计一个平均时间为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

算法描述

题目提示得很明白,要对所给数组数组进行划分,因此需要写一个partition函数定义left和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函数继续在左段或右段查找。

具体代码如下:

#include<iostream>
using namespace std;
int partition(int a[], int left, int right)
{
    int i = left, j = right + 1;
    int x = a[left];
    while(left < right)
    {
        while(a[++i] < x && i < right);
        while(a[--j] > x);
        if(i >= j)
            break;
        swap(a[i], a[j]); 
    }
    a[left] = a[j];
    a[j] = x;
    return j;    
}
int find(int a[], int left, int right, int k)
{
    int t = partition(a, left, right);
    if(k - 1 == t)
        cout << a[k - 1];
    else if(k - 1 < t)
        find(a, left, t, k);
    else 
        find(a, t + 1,right, k);
    return 0;
}
int main()
{
    int a[1000];
    int n, k;
    cin >> n >> k;
    for(int i = 0; i < n; i++)
    {
        cin >> a[i];
    }
    find(a, 0, n - 1, k);
    return 0;
}

 

算法时间及空间复杂度分析(要有分析过程)

时间复杂度:

快速排序算法在数组中选择一个元素,将数组分为两部分,使得 第一部分中的所有元素都小于或等于该元素,而第二部分的所有元素都大于该元素。对第一部分递归地应用快速排序算法,然后对第二部分递归地应用快速排序算法。  

最坏情况:划分的两个区域分别包含n-1个元素和1个元素,如果每一步都出现这种情况,其复杂性为 O(1) n≤1 T(n)= T(n-1)+O(n) n>1 解得:T(n)=O(n2)

最好情况:每次划分所取的基准都恰好为中值,即每次划分都产生两个大小为n/2的区域, O(1) n≤1 T(n)= 2T(n/2)+O(n) n>1 解得:T(n)=O(nlogn)

空间复杂度:

  空间复杂度我还不会算,上网查了一下。

  最优的情况下空间复杂度为:O(logn)  ;每一次都平分数组的情况

  最差的情况下空间复杂度为:O( n )      ;退化为冒泡排序的情况

  https://blog.csdn.net/A_BlackMoon/article/details/81064712

心得体会(对本次实践收获及疑惑进行总结)

  如果是老师课上讲了这个知识点然后让我们做的话,我可能这道题会特别难下手,甚至思绪千奇百怪,但是我又绝对这道题很好,几乎是全结合上了老师讲的内容,对我来说无疑是加深知识的好题,当时和同伴在上机时,时常卡到我们的点的就是段错误问题,不过到现在我都还是不知道怎么去避免段错误,只能不断地试,试着是不是因为这个原因错了,还是什么原因错了,上机两次,都是段错误的问题,第一次的段错误找了特别久才能找到,这道题的段错误试着找就被找到了,但我还是不知道段错误到底是怎么回事,上网查了也有好些原因,但有时套进题里就是不知道怎么改它了。

posted @ 2020-10-08 20:42  林冬璇  阅读(151)  评论(0编辑  收藏  举报