算法第二章上机实践报告

一、实践题目名称

找第k小的数
 

二、问题描述

在n(1<=n<=1000)个无序整数中寻找第k小的数,平均时间复杂度需为O(n)

输入格式:

输入有两行:

第一行是n和k,0<k<=n<=10000

第二行是n个整数

输出格式:

输出第k小的数

输入样例:

10 4
2 8 9 0 1 3 6 7 8 2

输出样例:

2

三、算法描述

1、算法思路:

Partition函数:

  选择第一个作为标准数(中轴),将数组中比x小的元素放在x左边,比x大的放在右边,最终稿返回中轴元素的位置。

Find函数:

  通过调用partition函数获得划分点,判断划分点是否第k小(因为首元素下标为0,注意是k-1来判断),若是,输出该划分点;若不是则递归查找,直到找出第k小的数。

2、具体代码

#include <iostream>
using namespace std;

int partition(int a[], int left, int right)

{//将数组a的第left到right个元素进行划分
    if(left==right) return left;
    int i=left,j=right+1;
     int x=a[left];//标准数 
     while(1)
     {
          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)

{//在数组a的第left到right中寻找第k小的数

    int mid = partition(a, left, right);

    if (k - 1 == mid)

        cout << a[mid];

    else if (k - 1 < mid)//判断下一次划分在哪一区间进行

        find(a, left, mid - 1, k);

    else if (k - 1 > mid)

        find(a, mid + 1, right, k);
return 0; } int main() { int n, k; cin >> n >> k; int a[1000]; for (int i = 0; i < n; i++) cin >> a[i]; find(a, 0, n - 1, k); return 0; }

 

四、算法时间及空间复杂度分析

1、时间复杂度

在partition函数中对整个数组进行了遍历,而find函数运用了二分思想,所以T(n) = O(n) + T(n/2) =  O(n)

2、空间复杂度:

在find函数中使用到了递归调用,需要开辟辅助空间,递归过程空间复杂度为O(logn),所以总的S(n) = O(logn)

五、心得体会

1、本次的实践让我对分治法更加熟悉的运用

2、在寻找第k小数的过程中一直没注意初始下标为0的问题,导致一直在寻找第k+1个数

3、许多方法的思想都在上学期学习过,需要另外复习上学期数据结构的内容

posted @ 2020-10-04 19:28  Takoyaki  阅读(117)  评论(0编辑  收藏  举报