问题描述:选择问题是求一个n个数列表的第k个最小元素的问题,当k==1或者k ==n,时,可以只扫描整个列表,分别找出最小值或者最大值。

这个问题有意思的是当k=n/2时,它要求找出一个这样的元素,这个元素比前半部分列表的元素都要大,又比后半部分的元素都要小,这个中间的值叫做中值。

这里我们要了解到一个划分的思想,将一个给定的列表根据某个值p进行划分,一般来说,列表元素会重新整理,使得左边部分的元素都是小于p的,紧接着就是中轴p本身,然后是右边部分都是大于p的

划分

  1. Lomuto划分,考虑一个数组—或者更一般的,一个子数组a【l,,,r】,该数组由连续的三段组成,这三段按顺序排在中轴p的后面:

    1. 一段为已知小于p的元素
    2. 一段已知大于或者等于p的元素
    3. 一段未和p比较过的元素
      在算法开始阶段,1,2情况都是空的

从i=l+1,开始,算法从左到右扫描子数组a,并保持这个结构直到划分完成,在每一次迭代中,它把未知段中的第一个元素与中轴p进行比较。

  • 如果a【i】>=p,则i++;,好比扩大了大于等于p元素的段,同时缩小了未处理的段。
  • 如果a【i】<p,则小于p元素的段需要扩大,通过s++实现,s指向第一段中的最后一个元素,在交换a【i】和a【s】,然后i++;使他指向缩小后未处理段的第一个元素。在未处理段为空后,算法把中轴和a【s】交换,就得到了一个我们所要求的划分

C语言实现

int  lomutopartition(int a[],int start,int end)
{int p=a[start];//把数组的第一个元素作为中轴p值int s=start;for(int i=start+1;i<=end;i++)//这里的i++,表示在不停的在遍历未处理段//从i=start+1,开始,算法从左到右扫描子数组a,//在每一次循环中,它把未知段中的第一个元素与中轴p进行比较{if(a[i]<p)//如果未知段的元素小于中轴p,小于p元素的段需要扩大{s++;//扩大,s++swap(a,s,i);//交换a【i】和a【s】}}swap(a,start,s);//未处理段为空,都处理好了,交换中轴p值和a【s】//这里的a【s】是小于p值的段的最后一个元素,所以交换后//中轴p的左边都是小于p的,右边都是大于等于p的。return s;//返回此时中轴的下标
}

如何利用划分列表来寻找第k个最小的元素呢?
假设列表以数组实现,元素的下标索引从0开始,而s是划分的分割位置,也就是划分后中轴所在元素的索引,如果s=k-1,中轴p本身显然就是第k小的元素,问题就解了,如果s>k-1,整个列表的第k小元素就是被划分中轴左边部分子数组的第k小元素,而如果s<k-1,就是中轴右边子数组部分的第(k-1-s)个小元素。因此,即使我们没有彻底解决问题,问题的规模得以变小,这个小实例可以使用同样的方法来解决,就是递归求解

C语言实现:

int  quickselect(int a[],int start,int end,int k)
{int s=lomutopartition(a,start,end);//得到这个中轴的下标sif(s==start+k-1)//如果s==第k-1个位置,那么a【s】就是第k小的数(下标从0开始的)return a[s];else if(s>start+k-1)//如果s>第k-1个位置,那么就从子数组【start,s-1】中去找第k小的数quickselect(a,start,s-1,k);else//如果s<第k-1位置,那么就从子数组【s+1,end】中去找第(start+k-1-s)小的数quickselect(a,s+1,end,start+k-1-s);//关于这里为什么递归的是start+k-1-s,因为这里传递子数组的起始下标是start+k-1.
}
下面举一个例子来

说明,基于划分的思想找出下面9的数列表中的中位数:
4,1,10,8,7,12,9,2,15.这里中位数k=5,任务就是找到数组中第五小的元素,在数组中的下标就是4.

下面给出一组图片说明具体的过程

C语言完整实现

#include<stdio.h>
void swap(int a[],int i,int j)
{int temp=a[i];a[i]=a[j];a[j]=temp;}
int  lomutopartition(int a[],int start,int end)
{int p=a[start];int s=start;for(int i=start+1;i<=end;i++){if(a[i]<p){s++;swap(a,s,i);}}swap(a,start,s);return s;
}
int  quickselect(int a[],int start,int end,int k)
{int s=lomutopartition(a,start,end);if(s==start+k-1)return a[s];else if(s>start+k-1)quickselect(a,start,s-1,k);elsequickselect(a,s+1,end,start+k-1-s);
}
int main()
{int a[]={12,1,20,100,52,10};//处理的数组int start=0;//数组的起始下标为0,int end=5;//数组的结束下标是5int k=5;//找出数组中第5小的数int res;res=quickselect(a,start,end,k); printf("%d",res);return 0;
}

减可变规模算法—中值和选择问题相关推荐

  1. 算法笔记_031:计算中值和选择问题(Java)

    目录 1 问题描述  2 解决方案 2.1 计算中值问题 2.2 选择问题   1 问题描述 中值问题是求一个n个数列表中某一数组下标k,它要求该下标元素比列表中的一半元素大,又比另一半元素小,这个中 ...

  2. 机器学习100天(三十):030 K近邻分类算法-K值的选择

    机器学习100天,今天讲的是:K近邻分类算法-K值的选择. <机器学习100天>完整目录:目录 上一节我们讲了 K 折交叉验证的理论,下面我们将 K 折交叉验证算法应用到 K 近邻分类算法 ...

  3. 图像降噪算法——中值滤波/均值滤波/高斯滤波/双边滤波

    图像降噪算法--中值滤波/均值滤波/高斯滤波/双边滤波 图像降噪算法--中值滤波/均值滤波/高斯滤波/双边滤波 1. 基本原理 2. C++代码实现 3. 结论 图像降噪算法--中值滤波/均值滤波/高 ...

  4. k近邻算法中k值得选择

    k值得选择会对k近邻的结果产生重大的影响  如果选择较小的K值,就相当于用较小的邻域中的训练实例进行预测,"学习"的近似误差会减小,只有输入实例较近的训练实例才会对预测结果起作用. ...

  5. ASP.NET中DropDownList控件的简单使用--DDL绑定数据库表中值,选择DDL中值直接检索数据...

    1.在.aspx页面拖入DropDownList控件 <label class="txt-green">校区:</label> <asp:DropDo ...

  6. matlab中基于十字形窗口的滤波算法,#215;字形滤波窗口在Matlab自适应中值滤波算法中的应用 - 21ic中国电子网...

    由于种种原因,图像在生成.传输.变换等过程中往往会受到各种噪声的污染,从而导致图像质量退化.噪声信号的滤波是图像处理的基本任务之一,主要有线性滤波和非线性滤波两种方法.线性滤波方法一般具有低通特性,而 ...

  7. 计算中值——如何快速找到一个数组的中值

    在统计学中,中值往往比平均值更能体现一组数据的特点,因为不会被两边的极端数据影响. 那么要找到一个无序数组的中值,可以先将数组中的数据排序,然后直接返回数组中间的数据即可,但是我们要想到,仅仅只是为了 ...

  8. OpenCV3学习(4.2)——图像常用滤波方法(方框、均值、高斯、中值、双边)

    滤波处理分为两大类:线性滤波和非线性滤波.OpenCV里有这些滤波的函数,使用起来非常方便,现在简单介绍其使用方法. 线性滤波: 1.方框滤波:模糊图像 2.均值滤波:模糊图像 3.高斯滤波:信号的平 ...

  9. MATLAB自适应中值滤波

    % 自适应中值滤波 clc,clear,close all % 清理命令区.清理工作区.关闭显示图形 warning off % 消除警告 feature jit off % 加速代码运行 [file ...

最新文章

  1. 人工智能让育种“物美价廉”
  2. 使用OpenCV-Python的函数minMaxLoc()应该注意的两点
  3. hdu 4336 Card Collector
  4. POJ 3177 Redundant Paths (边双连通+缩点)
  5. chrome 插件 vimium 介绍
  6. iOS之深入解析GCD的底层原理
  7. python3动态加载模块的方法实现
  8. Android开发/源码资源汇总
  9. Android的JNI【实战教程】4⃣️--C调用Java代码
  10. hmcl手机版_hmcl启动器手机版下载-hmcl启动器 安卓版v1.1.4-PC6安卓网
  11. hr面试高频问题回答思路总结
  12. 手机变身电脑摄像头 Droidcam使用
  13. 基于89C51单片机的智能语音拨号电话
  14. 腾讯云如何设置二级域名?
  15. openoffic+java+spring 多线程 转换doc,ppt,xls - html/pdf
  16. replacestate 后退刷新_关于如何禁止浏览器后退及刷新功能
  17. html多个背景音乐自动播放,多个背景音乐同时自动播放?
  18. java verbose gc_java –verbose:gc
  19. AI提取图片里包含的文字信息-解决文字无法复制的痛点
  20. 主 题: atl中传HRESULT func4([out] BSTR* pVal); 怎么调用都不能将值返回呢?是不是javascript不支http://topic.okbase.net/

热门文章

  1. SYMFONY 助手
  2. GetTempPath
  3. 远离浮躁,重视基础。
  4. 浅谈Joomla!流行模板的修改方法
  5. 巫师3计算机,游戏巫师3电脑配置要求是什么
  6. java中跳出循环终止循环_js for终止循环 跳出多层循环
  7. 计算机折线图教程,怎么在电脑版Excel中将图表添加
  8. Linux下用户的创建与删除
  9. Xcode 调试方法总结
  10. 会展管理SaaS如何利用帮助中心来提升服务水平?