实验二:线性时间选择

2023-05-16

实验二:线性时间选择

 

  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 number

        while (i<j)
        {
            //from right to left,find a number smaller than standard number
            while (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 75
    if(right-left<75){
        QuickSort(nums,left,right);
        return nums[left+target-1];
    }
    //NOT 75
    for(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-5
        int 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;
}

 

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

实验二:线性时间选择 的相关文章

  • React Hooks removeEventListener 使用无效问题

    组件卸载时 和原来的componentWillUnmount一样的用法 在useEffect return里调用就可以了 span class token function useEffect span span class token p
  • 关于git:fatal:无法访问’https://github.com/xxx’:OpenSSL SSL_connect:SSL_ERROR_SYSCALL连接到github.com:443

    如果您使用代理 xff0c 请尝试运行并输入inetcpl cpl 然后连接 xff0c 然后局域网设置 xff0c 然后前进 现在您可以看到您的代理 xff0c 使用http代理 然后打开Git Bash xff0c 然后输入此命令 gi
  • flutter 监听软键盘的弹出和关闭

    实现 继承 with WidgetsBindingObserver 1 初始化监听 span class token comment 初始化监听页面高度 span WidgetsBinding span class token punctu
  • android-studio 项目启动 镜像源加速

    解决android studio download maven metadata xml卡住问题 https blog csdn net hzw2017 article details 114776815 android studio 阿里
  • 基于vue3 beego vue-beegoBackstage 后台管理系统

    基础 在线访问地址 vue3 go admingithub访问 vue3 go admin 功能 用户管理 lt gt 关联角色角色管理 lt gt 关联菜单菜单管理部门管理字典管理登录 权限校验动态路由生成 按钮权限菜单栏切换面包屑tab
  • Build Dense Trajectory Codes in Ubuntu

    Even when the OpenCV and ffmpeg have been successfully installed you still may meet the error of 34 undefined reference
  • javascript 数组拆分为3个一组

    span class token keyword const span a span class token operator 61 span span class token punctuation span span class tok
  • win10美化工具全套详细解析

    1 xff0c 任务栏透明工具StartllsBack 1 xff0c 首先安装 xff0c 选第一个为当前用户安装 xff08 这个选哪个都可以的 xff09 2 xff0c 然后就是设置这个任务栏透明了 xff0c 右键 开始 菜单找到
  • 前后端分离的情况下生成activiti流程图

    页面用调接口的方式 xff0c 将图片流显示 效果图 xff1a 注意 xff1a 布署到有些最小安装的linux服务器时 xff0c 用户任务框里面的中文会显示不出来 xff0c 这是因为缺少系统字体 宋体 xff0c 需要在服务器安装字
  • Linux文件系统变成只读的解决方法

    解决方法 1 重启看是否可以修复 xff08 很多机器可以的 xff09 2 使用用 fsck y dev hdc6 dev hdc6指你需要修复的分区 来修复文件系统 3 若 xff0c 在进行修复的时候有的分区会报错 xff0c 重新启
  • 19-29-k8s-基本命令-yaml-kubectl

    19 k8s 基本命令 yaml kubectl xff1a Kubernetes 集群的命令行工具kubectl 1 kubectl 命令格式 xff1a kubectl command type name flags 参数 xff1a
  • linux下安装nginx

    linux下安装nginx 注 xff1a 此处需要先安装vmware xff0c 下载Centos8等工具 xff0c 配置好一个虚拟机 1 下载nginx的linux版本 2 上传至搭建好的linux环境上 3 解压nginx压缩包 4
  • 128-152-spark-核心编程-源码

    128 spark 核心编程 源码 xff08 主要以了解基本原理和流程为主 xff09 xff1a 总体相关 1 环境准备 Yarn 集群 1 Driver Executor 2 组件通信 1 Driver 61 gt Executor
  • 6-zookeeper-hadoop-ha原理简述-fail

    6 zookeeper hadoop ha故障转移机制 xff0c 原理简述 HA概述 xff08 2 X版本架构 xff09 1 xff09 HA xff08 High available xff09 xff0c 即高可用 xff08 7
  • treelistview入门使用

    treelistview入门使用 1 创建窗口程序 2 引入库System Runtime InteropServices APIs dll和System Runtime InteropServices APIs dll 3 工具箱添加控件
  • ps-01

    ps 01 入门 xff1a 来源尚硅谷ps课程 xff0c 兴趣而已 xff0c 仅做记录 内容无实质性操作指导 1 软件安装 百度参考各种连接 xff0c 自己安装 https baiyunju cc 10433 2 基础操作 2 1打
  • Notes of Dense Trajectory

    Dense Trajectories densely sample feature points in each frame track points in the video based on optical flow compute m
  • python解析xml文件(解析、更新、写入)

    Overview 这篇博客内容将包括对XML文件的解析 追加新元素后写入到XML xff0c 以及更新原XML文件中某结点的值 使用的是python的xml dom minidom包 xff0c 详情可见其官方文档 xff1a xml do
  • 统计字符串中出现次数最多的字母及其出现次数C++

    小弱鸡看不太懂别人的代码 xff0c 于是用了结构体的方法 xff0c 将字母及其出现次数打包 xff01 include lt iostream gt include lt string h gt include lt algorithm
  • 安装man中文

    安装 man 中文手册 在使用 mac 或者 linux 的时候 xff0c 需要用到命令 xff0c 而大量的命令含有大量 options xff0c 一般很难记住 xff0c 使用 man 可以查看这些命令的 options xff0c

随机推荐

  • Ubuntu 18.04安装PyCharm社区版

    下载 下载 xff1a 或直接官网下载 链接 xff1a https pan baidu com s 1JLmMqJNBvClLAYuK1rlKrw 提取码 xff1a 41qk 安装 下载完后进入到存储文件的地址执行以下代码 xff0c
  • Android安卓动态获取存储权限,保存文件到外部存储

    添加存储权限 lt 外部存储的写权限 gt lt uses permission android name 61 34 android permission WRITE EXTERNAL STORAGE 34 gt lt 外部存储的读权限
  • 按键消抖详解

    一 按键消抖原理 抖动时间的长短由按键的机械特性决定 xff0c 一般为 5ms xff5e 10ms xff0c 键抖动会引起一次按键被误读多次 解决办法 xff1a 判断按键按下时 xff0c 延时 10 ms 即可 二 软件实现按键消
  • 20 分钟梳理 Spring 全家桶 !

    作 者 xff1a Daisy 授权转自IT技术思维 xff0c 每日精选优质干货 xff0c 欢迎关注 xff01 xff1e xff1e xff1c xff1c Spring框架自诞生以来一直备受开发者青睐 xff0c 有人亲切的称之为
  • Linux添加软件分类(GNOME桌面)

    Linux添加软件分类 xff08 GNOME桌面 xff09 之前安装TIM deepin wine 的时候发现TIM的分类为chat xff0c 而系统默认没有这个分类 xff0c 所以TIM就很自然的被划分到 其他 里边去了 这强迫症
  • gnome扩展推荐

    引言 xff1a gnome在Linux世界里作为一个比较流行的桌面环境 xff0c 默认不是十分美观 xff0c 有些功能也没有 xff0c 这个时候我们就可以选择安装扩展去个性化gnome 下面是我的桌面截图 xff0c 我利用了扩展实
  • SpringBoot + Redis实现布隆过滤器

    一 简述 关于布隆过滤器的详细介绍 xff0c 我在这里就不再赘述一遍了 我们首先知道 xff1a BloomFilter使用长度为m bit的字节数组 xff0c 使用k个hash函数 xff0c 增加一个元素 通过k次hash将元素映射
  • 屏蔽效能预估

    今天完成了屏蔽效能预估部分的程序 由于公式比较多 xff0c 而且就编程本身而言技术含量不高 xff0c 因此不将源代码贴出 xff0c 有需要者可以联系我 程序界面如下 xff1a
  • SSH 命令的11种用法

    使用ssh连接远程主机 最简单的用法只需要指定用户名和主机名参数即可 xff0c 主机名可以是 IP 地址或者域名 ssh user 64 hostname ssh连接到其他端口 SSH 默认连接到目标主机的 22 端口上 xff0c 可以
  • Spring配置的可选方案(三种配置方式)

    版权声明 xff1a 本文摘自 Spring实战 第4版 xff0c 美 Craig Walls 著 xff0c 张卫滨 译 本文仅作为学习与交流使用 xff0c 如有侵权请留言联系作者 转载请注明出处 目录 一 自动化装配Bean 注释
  • ftp工具

    本文会介绍java代码的ftp工具使用 xff0c 代码实现的功能难免不全 xff0c 要完整的体验ftp功能 xff0c 建议使用该ftp工具 xff1a iis7服务器管理工具 iis7服务器管理工具 xff08 曾用名 xff1a I
  • windows server 2000 r2 设置FTP文件服务器

    最近有一个需求需要将我们自己的一台windows服务器设置文件服务器 xff0c 小小记录一下 xff0c 设置过程 搭建IIS 第一步 xff1a 打开控制面板 第二步 xff1a 点击 打开或关闭 Windows 功能 第三步 xff1
  • ubuntu通过shell脚本实现服务自启和自动关机

    通常服务器开启后需要输入一大堆繁琐的进入文件 启动服务等命令 xff0c 每天如此就会逼着自己寻找捷径 xff0c 毕竟时间不用来学习就是在浪费生命嘛 xff1a Shell脚本挺身而出 xff1a 实现 xff1a 1 配置开机root账
  • 是什么导致了nginx.service: control process exited, code=exited status=1?

    是什么导致了nginx service control process exited code 61 exited status 61 1 xff1f 今天使用脚本安装nginx服务时遇到下面的问题 xff1a 那就先敲命令呗 xff0c
  • .jar与sources.jar区别

    首先 xff0c 当我们在下载jar包与引入jar包的时候可能会发现 xff0c 存在jar文件与相应的sources jar文件 如下图所示 xff1a 这个时候 xff0c 到底该下载哪一个 xff0c 或者我们需要的是哪一个 是jun
  • bat暂停5秒

    choice T 5 C ync CS D y n
  • Linux 开机自启动

    一 无界面的程序自启动 etc rc local 1 编辑 etc rc local vi etc rc local 2 添加要执行的命令 在exit 0 之前 注意 xff1a 这里的执行命令都必须是全路径的 xff0c 就算你添加到了
  • 使用firefox color自定义firefox的主题

    本说明基于firefox 79 轻量级主题 引用 xff1a firefox关于主题的说法 xff0c firefox现在仅支持轻量级主题了 那么什么是轻量级主题呢 xff1f mozilla官方并没有明确的定义 xff0c 我的理解是 x
  • TCL判断条件

    编写TCL代码时遇要写一个if判断条件 xff0c 很简单的一个语句 xff0c 结果却费了很大力气才搞定 要判断的是 xff0c 如果执行info exists成功而且某全局数组C的某个成员大于0 xff0c 正确的语句为 xff1a i
  • 实验二:线性时间选择

    实验二 xff1a 线性时间选择 问题描述 xff08 1 xff09 线性时间选择问题 给定线性序集中n个元素和一个整数k xff0c 1 lt 61 k lt 61 n 要求找出这n个元素中第k小的元素 xff0c 即如果将这个n个元素