实验二:线性时间选择

  1. 问题描述

(1)线性时间选择问题

给定线性序集中n个元素和一个整数k,1<=k<=n.要求找出这n个元素中第k小的元素,即如果将这个n个元素依其线性序排列时,排在第k个位置的元素就是要找的元素,当k==1时,要找的就是最小的元素;当k==n,就是最大的元素;当k=(n+1)/2,称为中位数。

  1. 实验目的

(1)掌握线性时间选择算法

(2)体会线性时间选择算法中蕴含的分治思想

  1. 实验原理

分治算法的基本思想是将一个规模为N的问题分解为K个规模较小的子问题,这些子问题相互独立且与原问题性质相同。求出子问题的解,就可得到原问题的解。即一种分目标完成程序算法,简单问题可用二分法完成。

(3)线性时间选择

一个很简单的想法就是先排序后找,但这样算法的性能依赖于所选择排序算法的性能,比如快排就很快,冒泡就很慢。

我们可以模仿快速排序算法,对输入数组进行递归划分。与快速排序不同的是,它只对划分出的子数组之一进行递归处理。

一种改进的思路是:如果能在线性时间内找到一个划分基准,使得按这个基准所划分出的两个子数组长度都至少为原数组长度的e倍(0<e<1是某个正常数),那么在最坏情况下用O(n)时间就可以完成选择任务。例如,若e=9/10,算法递归调用所产生的子数组的长度至少缩短1/10。所以,在最坏情况下,算法所需的计算时间Tn满足递归式Tn<=T(9n/10)+O(n)。由此可得T(n)=O(n)

(1)将n个输入元素划分成n/5个组,每组5个元素,除可能有一个组不是5个元素外。用任意一种排序算法,将每组中的元素排好序,并取出每组的中位数,共n/5个。

(2)递归调用Select找出这n/5个元素的中位数。如果n/5是偶数,就找它的两个中位数中较大的一个。然后以这个元素作为划分基准。

(所有的n/5都向上取整,取整号打不出来。。。)

  1. 实验设计

4.1 线性时间选择

在前面快速排序的基础上进行线性时间选择。

首先是先排序后找target值。这种办法对于数组规模较小的情况有效。但对于大规模的数组,显然有更好的办法优化线性时间选择的算法。

整个c文件分为5个函数:

1. swap交换函数。C语言没有原生的swap交换函数,因此自己写了一个。

2. Partition分区函数。用于对给定数组进行分区。

3. random函数。用于生成一定范围内的随机数。利用c语言原生的rand函数生成随机数,srand函数配合time.h的time函数播种种子。

4. Quicksort函数。上个文件的。

5. Select函数。用于选择和排序。

这几个函数有一部分是从上个快速排序函数继承下来的。

  1. 实验结果与分析

5.1 线性时间选择

首先,线性时间选择存在越界可能性,即选择的target值超过数组本身范围,会打印出内存中的随机数。(c语言)截图如下:

除去越界问题,对线性时间选择的性能测试如下:

选择target=4(随便想的),在10,100,1 000,10 000,100 000顺序数组查找的时间如下(忽略生成时间和打印时间):

数字个数

时间

10

0.385

100

0.347

1000

0.350

10000

0.450

100000

0.480

图表体现的不是那么明显,一方面是c语言没有直接测量时间的函数,只能依赖于编译器给出的时间,但这个时间并不是绝对精确的;另一方面,时间包含了生成随机数和打印的时间,虽然最终的结果应该随着x坐标是线性的,但体现不明显。

查阅资料得知,c语言有时间测量模块time_t。我决定用time_t改良时间测量的精确性。同时将数据改为线性数据。改进后重新实验:

数据

时间(精确,ms

10 000

0

20 000

1.2

30 000

2.0

40 000

2.4

50 000

4.0

60 000

4.6

70 000

5.4

80 000

6.4

90 000

6.0

100 000

6.2

这次的线性就体现得很明显了。

  1. 结论

线性时间选择的优化来自快速排序对基准数的优化,从自选数(一般为第一位),到随机数,最后是中位数。

算法

快排

随机选择

线性时间选择

时间复杂度

O(nlog(n))O(nlog(n))

O(n)−−O(n2)O(n)−−O(n2)

O(n)O(n)

基准值

a[p]

random

中位数

  1. 程序源码

7.1线性时间选择

#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#include<unistd.h>// Swap the district
void Swap(int a,int b){int temp=a;a=b;b=temp;
}int Partition(int nums[],int left,int right,int x){int i=left,j=right+1;//int x=nums[left];while (1){while (nums[++i]<x&&i<right);while (nums[--j]>x);if(i>=j)break;Swap(nums[i],nums[j]);}nums[left]=nums[j];nums[j]=x;return j;
}int random(int max,int min){int origin = rand();int random_num = origin%(max-min+1)+min;return random_num;
}// int RandomizedPartition(int a[],int p,int r){
//     srand((unsigned int)time(NULL));
//     int i=random(p,r);
//     Swap(a[i],a[p]);
//     return Partition(a,p,r);
// }int QuickSort(int nums[],int left,int right){//@param: nums[]: numbers//@param: left: the number of the [0]if(left<right){int i=left;int j=right;int temp_middle=nums[left];//standard numberwhile (i<j){//from right to left,find a number smaller than standard numberwhile (i<j&&nums[j]>=temp_middle){j--;}if(i<j){nums[i]=nums[j];i++;}while (i<j&&nums[i]<temp_middle){i++;}if(i<j){nums[j]=nums[i];j--;}           }nums[i]=temp_middle;QuickSort(nums,left,i-1);QuickSort(nums,j+1,right);        }
}int Select(int nums[],int left,int right,int target){//judge by 75if(right-left<75){QuickSort(nums,left,right);return nums[left+target-1];}//NOT 75for(int i=0;i<=(right-left-4)/5;i++){//right-left-4 是一个划分组号的公式。比如组内有34个元素,//i的值就是(33-0-4)/5=29/5=5//找中位数的中位数,r-p-4即上面所说的n-5int s=left+5*i,t=s+4;for(int j=0; j<3; j++) //冒泡排序,从后开始排,结果使得后三个数是排好顺序的(递增){for(int n=s; n<t-j; n++){if(nums[n]>nums[n+1])Swap(nums[n],nums[n-1]);}}Swap(nums[left+1],nums[s+2]);}int x=Select(nums,left,left+(right-left-4)/5,(right-left-4)/10);int i=Partition(nums,left,right,x),j=i-left+1;if(target<=j){// printf("target<=j,j=%d\n",j);// printf("##left=%d\n",left);// printf("##right=%d\n",right);return Select(nums,left,i,target);}else{// printf("target>j,j=%d\n",j);// printf("##left=%d\n",left);// printf("##right=%d\n",right);return Select(nums,i+1,right,target-j);}}int main(void){int target=4;//int nums[100]={3,1,7,6,5,9,8,2,0,4,13,11,17,16,15,19,18,12,10,14,23,21,27,26,25,29,28,22,20,24,33,31,37,36,35,39,38,32,30,34,43,41,47,46,45,49,48,42,40,44,53,51,57,56,55,59,58,52,50,54,63,61,67,66,65,69,68,62,60,64,73,71,77,76,75,79,78,72,70,74,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100};int max_num=100000;int nums[max_num];for(int i=0;i<max_num;i++){        nums[i]=i+1;        // printf("%2d,",nums[i]);// if(nums[i]%10==0) printf("\n");}//计时clock_t stime = clock();if(target>max_num||target<=0){printf("越界了!");printf("越界结果:第%d大的数是%d\n",target,Select(nums,0,max_num,target));}else{printf("第%d大的数是%d\n",target,Select(nums,0,max_num,target));}clock_t etime = clock();printf("time is %d ms",etime-stime);return 0;
}

实验二:线性时间选择相关推荐

  1. 应用计算机测定线性电阻电路图和实物图,中国大学MOOC电子线路设计、测试与实验二网课答案...

    中国大学MOOC电子线路设计.测试与实验二网课答案 字体大小:大 | 中 | 小 2020-04-26 19:57 阅读(1017) 分类: 中国大学MOOC电子线路设计.测试与实验二网课答案 打开右 ...

  2. 单位斜变函数matlab,实验二 用MATLAB实现线性系统的时域分析

    实验二基于MATLAB的线性系统时域分析 [实验目的] 1.研究线性系统在典型输入信号作用下的暂态响应: 2.熟悉线性系统的暂态性能指标: 3.研究二阶系统重要参数阻尼比ξ对系统动态性能的影响: 4. ...

  3. matlab语言实验二,实验二 MATLAB语言基础

    实验二 MATLAB 语言基础 一.实验目的 基本掌握 MATLAB 向量.矩阵.数组的生成及其基本运算(区分数组运算和矩阵运算).常用的数学函数.了解字符串的操作. 二.实验内容 (1) 向量的生成 ...

  4. 实验二matlab数值,实验二MATLAB数值计算

    实验二MA TLAB数值计算 1.实验目的 (1)掌握MA TLAB变量的使用 (2)掌握MA TLAB数组的创建, (3)掌握MA TLAB数组和矩阵的运算. (4)熟悉MA TLAB多项式的运用 ...

  5. 实验一 线性表、堆栈和队列的操作与实现

    前言 记录实验,同时也是记录常见数据结构算法的实现. 广州大学学生实验报告 开课实验室:计算机科学与工程实验(电子楼418A) 学院 计算机科学与网络工程学院 实验课程 数据结构实验 实验项目 实验一 ...

  6. 算法设计与分析——递归与分治策略——线性时间选择

    顾名思义:这篇文章讲解的就是如果用线性时间算法来作出元素选择问题. 问题描述:给定线性序集中n个元素和一个整数k,1<=k<=n.要求找出这n个元素中第k小的元素,即如果将这个n个元素依其 ...

  7. 实验二 matlab矩阵分析与处理

    实验二 matlab矩阵分析与处理 目录 实验二 matlab矩阵分析与处理 2 1.1实验目的 3 1.2实验内容 3 1.3流程图 4 1.4程序清单 4 1.5运行结果及分析 6 1.6实验的收 ...

  8. 实验二 语音信号基本时频分析(待更改)

    实验二 语音信号基本时频分析 1.实验目的 1.1 学习与掌握语音信号的分帧及加窗 1.2 了解并分析信号加汉明窗及矩形窗后的差别 1.3 分析清音与浊音的时域及频谱域波形特征(画图.对比) 1.4 ...

  9. 本科课程【数据结构与算法】实验1——线性表的顺序表示及插入、删除操作(C++实现)

    大家好,我是[1+1=王], 热爱java的计算机(人工智能)渣硕研究生在读. 如果你也对java.人工智能等技术感兴趣,欢迎关注,抱团交流进大厂!!! Good better best, never ...

  10. 操作系统实验二:物理内存管理系统

    操作系统实验二:物理内存管理系统 一. 实验目的 二. 实验内容 三. 实验准备 [实验概述] [关键数据结构] [执行流程] 四. 实验步骤 (一) 练习0:填写已有实验 (二) 练习1:实现 fi ...

最新文章

  1. spring常用的三种依赖注入方式
  2. 2017-9-13:学习笔记
  3. Xamarin Essentials教程设备信息DeviceInfo
  4. python--open用法
  5. numpy基础(part8)--符号数组与矢量化
  6. 工作69:发布商品页面
  7. 计算机技术与通讯,通信技术与计算机技术的融合发展
  8. GCD API 理解 (一)
  9. shuffle洗牌算法java_js打乱一个数组 的 洗牌(shuffle )算法
  10. jsp mysql论坛_体育论坛ssm,mysql)
  11. Maven 插件介绍
  12. 2021年全球及中国企业级路由器市场竞争格局分析,呈现出寡头竞争的市场格局「图」
  13. sk hynix 固态硬盘 管理_5000MB/s 极速狂飙——希捷酷玩FireCuda 520 PCIE4.0 SSD固态硬盘体验...
  14. python将姓王的都改成老王_全域明星-第46章:校长姓王,隔壁老王?-爱阅小说网...
  15. 翻译:理解特征工程(1)-连续数值数据
  16. 【JAVA】 容纳对象 数组
  17. 音视频从入门到精通——FFmpeg分离出PCM数据实战
  18. HTML标签检查工具
  19. 机器人逆运动学公式推导中常用的方程求解
  20. VR全景婚礼记录最幸福的那一刻

热门文章

  1. QEMU文档之bypass iommu
  2. matlab 画图 浓淡有别,matlab画图命令汇总
  3. 解决:Word仿宋字体显示不正确,仿宋GB2312的问题
  4. APP自动化效果测试工具
  5. 从各方面比较一下各类电脑玩手游吃鸡安卓模拟器
  6. 产品需求文档(PRD,Product Requirement Document)模板
  7. eplan p8详细安装步骤文库_Win10系统安装Eplan Electric P8详细步骤
  8. HAWQ取代传统数仓实践(一)——为什么选择HAWQ
  9. gps天线拆解图片_GPS天线原理解析
  10. 通达信手机版分时图指标大全_通达信手机版指标源码大全,响应大家要求今日直接附上,快来收藏...