• 算法第二章上机实验报告


    实践题目

       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

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

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

  • 相关阅读:
    vue 样式使用总结
    安卓内嵌H5只展示部分静态页面
    Excel 2016入门与提高
    Oracle Exadata技术详解
    计算机网络基础
    Photoshop扁平化平面设计手册
    C程序设计伴侣——帮你更好地理解谭浩强老师的那本书以及更多!
    中文版Project 2007实用教程
    新手学CorelDRAW X8商业设计200+
    Altium Designer 17电路设计与仿真从入门到精通
  • 原文地址:https://www.cnblogs.com/ldx539/p/13782648.html
Copyright © 2020-2023  润新知