算法第二章上机实践报告

要求:

实践报告任选一题进行分析。内容包括:

  1. 实践题目名称
  2. 问题描述
  3. 算法描述
  4. 算法时间及空间复杂度分析(要有分析过程)
  5. 心得体会(对本次实践收获及疑惑进行总结)

实践题目:2-1 找第k小的数 (25分)

问题描述:

设计一个平均时间为O(n)的算法,在n(1<=n<=1000)个无序的整数中找出第k小的数。

算法描述

(快速排序)

函数int partition(int a[],int left,int right):用第一个数作为基准点,将比它小的数放在左侧,比它大的数放在右侧。i从左往右扫,j从右往左扫,在不交叉的情况下(i

函数find(int a[],int left,int right,int k):调用partition函数获得基准点,将返回的划分点j与k比较。(在此划分点的左边为小数,右边为大数,所以比较即可知道第k小的数的范围。)

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

时间复杂度

partition算法的时间复杂度O(n),最坏情况下,会将n个元素分为n-1与1的组合,此时T(n)=O(n^2);

最好情况下,每次都产生n/2的区域,则此时T(n)=O(nlogn)

空间复杂度

O(n),存放无序数的数组

心得体会

①一开始并没有想到是快速排序的思想,由于是要找第k小,而快速排序刚好满足这一特点,数本身可能无序,但是总有前面数小,后面数大的情况。这正好满足第k小的特点,若元素位置与k-1相等,则说明为要找的数。

②一开始没有考虑到数组下标从0开始,而最小k为1.

代码

#include 
using namespace std;
 
int partition(int a[],int left,int right)
{
	int x = a[left];
	int i = left+1;
	int j = right;
	int temp;
	while(i          //若是一直比x小,则有越界的可能,所以要加i x)
		{
			j--;
		}
          //若是已经交叉了,则要break,停止交换,否则大数会跑到小数的位置 if(i>=j) break; temp = a[i]; a[i] = a[j]; a[j] = temp; }
    //基准点与a[j]的交换 a[left] = a[j]; a[j] = x; return j; } int find(int a[],int left,int right,int k) { int x = partition(a,left,right); if(x+1 == k) { return a[k-1]; } if(x+1 < k) { find(a,x+1,right,k); } else find(a,left,x-1,k); } int main() { int n,k; cin >> n >> k; int a[10002]; for(int i=0; i> a[i]; } cout << find(a,0,n-1,k); }

  

 

你可能感兴趣的:(算法第二章上机实践报告)