[图解算法]线性时间选择Linear Select——<递归与分治策略>
- #include <ctime>
- #include <iostream>
- using namespace std;
- template <class Type>
- void Swap(Type &x,Type &y);
- inline int Random(int x, int y);
- template <class Type>
- void BubbleSort(Type a[],int p,int r);
- template <class Type>
- int Partition(Type a[],int p,int r,Type x);
- template <class Type>
- Type Select(Type a[],int p,int r,int k);
- void main()
- {
- //初始化数组
- int a[];
- //必须放在循环体外面
- srand((unsigned)time());
- for(int i=; i<; i++)
- {
- a[i] = Random(,);
- cout<<"a["<<i<<"]:"<<a[i]<<" ";
- }
- cout<<endl;
- cout<<"第23小元素是"<<Select(a,,,)<<endl;
- //重新排序,对比结果
- BubbleSort(a,,);
- for(i=; i<; i++)
- {
- cout<<"a["<<i<<"]:"<<a[i]<<" ";
- }
- cout<<endl;
- }
- template <class Type>
- void Swap(Type &x,Type &y)
- {
- Type temp = x;
- x = y;
- y = temp;
- }
- inline int Random(int x, int y)
- {
- int ran_num = rand() % (y - x) + x;
- return ran_num;
- }
- //冒泡排序
- template <class Type>
- void BubbleSort(Type a[],int p,int r)
- {
- //记录一次遍历中是否有元素的交换
- bool exchange;
- for(int i=p; i<r;i++)
- {
- exchange = false ;
- for(int j=; j<=r-i; j++)
- {
- if(a[j]<a[j-])
- {
- Swap(a[j],a[j-]);
- exchange = true;
- }
- }
- //如果这次遍历没有元素的交换,那么排序结束
- if(false == exchange)
- {
- break ;
- }
- }
- }
- template <class Type>
- int Partition(Type a[],int p,int r,Type x)
- {
- int i = p-,j = r + ;
- while(true)
- {
- while(a[++i]<x && i<r);
- while(a[--j]>x);
- if(i>=j)
- {
- break;
- }
- Swap(a[i],a[j]);
- }
- return j;
- }
- template <class Type>
- Type Select(Type a[],int p,int r,int k)
- {
- if(r-p<)
- {
- BubbleSort(a,p,r);
- return a[p+k-];
- }
- //(r-p-4)/5相当于n-5
- for(int i=; i<=(r-p-)/; i++)
- {
- //将元素每5个分成一组,分别排序,并将该组中位数与a[p+i]交换位置
- //使所有中位数都排列在数组最左侧,以便进一步查找中位数的中位数
- BubbleSort(a,p+*i,p+*i+);
- Swap(a[p+*i+],a[p+i]);
- }
- //找中位数的中位数
- Type x = Select(a,p,p+(r-p-)/,(r-p-)/);
- i = Partition(a,p,r,x);
- int j = i-p+;
- if(k<=j)
- {
- return Select(a,p,i,k);
- }
- else
- {
- return Select(a,i+,r,k-j);
- }
- }
提醒:此篇需要先理解快速排序。
[图解+例子]
一、建立随机数组
(共27个数)(代码中为100个数,为了放得下举的例子改为27个)
二、给线性时间选择函数Select()传参
Type a[] 数组a
int p 起始位置
int r 结束位置
int k 查找第k小
三、判断
元素个数<75 不需要线性选择--》直接进行冒泡排序返回a[p+k-1](第k小元素)
元素个数>75 进行线性选择 --》进行下一步
四、线性时间选择
1- 分组并取各组中位数 (将元素每5个分成一组,分别排序,并将该组中位数与a[p+i]交换位置 )【图中绿线12345表示要交换的一对对数据】
for(int i=0; i<=(r-p-4)/5; i++)
{
BubbleSort(a,p+5*i,p+5*i+4);
Swap(a[p+5*i+2],a[p+i]);
}
目的:使所有组的中位数都排列在数组最左侧,以便进一步查找中位数的中位数
2- 查找中位数的中位数
Type x = Select(a , p , p+(r-p-4)/5 , (r-p-4)/10 );
p到p+(r-p-4)/5为中位数的范围,p+(r-p-4)/5 ÷ 2 = (r-p-4)/10-->中位数的中位数
----------------------------------------------------------------------------------------------------------
3-用找到的中位数的中位数做为快速排序的标准进行一趟快速排序(前面有篇讲的快速排序为了方便直接用第一个做标准,也有用随机数做标准的)
i = Partition(a,p,r,x);
排序结束后,标准元素将数组分为三部分:左,标准元素,右。
快排讲过啦,这里快速排序省略图解啦 !想看点这里 快速排序
------------------------------------------------------------------------------------------------------------
4-判断
快速排序后看成三部分:左,标准元素,右。
左都比标准元素小,右都比它大;(此时左右还是乱序,只有标准元素找到了它最终应该排的位置,这里不清晰先看快速排序那篇文章)
所以判断下我们要找的第k小是比它大(在右)还是比它小(在左);
int j = i-p+1;
if(k<=j)
{
return Select(a,p,i,k);
}
else
{
return Select(a,i+1,r,k-j);
}
i为快速排序返回值,j = i - 起始位置 + 1;
小于或者等于,对左半段重复上述操作(递归);
反之,对右半段。
-----------------------------------------------------------------------------------------------------------------
[特例]
有空更新。。。
[总结]
线性时间选择其实就是————>>快速排序的加强版,
快速排序中的标准元素变为————>>分组后取得的各组中位数的中位数。
所以多了一步取中位数的操作而已。
本人保留解析著作权。
算法引用自 王晓东. 计算机算法设计与分析[M]. 电子工业出版社, 2012.
[图解算法]线性时间选择Linear Select——<递归与分治策略>的更多相关文章
- 递归与分治策略之循环赛日程表Java实现
递归与分治策略之循环赛日程表 一.问题描述 设有n=2^k个运动员要进行网球循环赛.现要设计一个满足以下要求的比赛日程表: (1)每个选手必须与其他n-1个选手各赛一次: (2)每个选手一天只能参赛一 ...
- 递归与分治策略之棋盘覆盖Java实现
递归与分治策略之棋盘覆盖 一.问题描述 二.过程详解 1.棋盘如下图,其中有一特殊方格:16*16 . 2.第一个分割结果:8*8 3.第二次分割结果:4*4 4.第三次分割结果:2*2 5.第四次分 ...
- [图解算法] 归并排序MergeSort——<递归与分治策略>
#include"iostream.h" void Merge(int c[],int d[],int l,int m,int r){ ,k=l; while((i<=m)& ...
- [图解算法] 二分查找Binary-Search——<递归与分治策略>
#include"iostream.h" int BinarySearch(int a[],int left,int right,const int& x) { if(le ...
- 算法:线性时间选择(C/C++)
Description 给定线性序集中n个元素和一个整数k,n<=2000000,1<=k<=n,要求找出这n个元素中第k小的数. Input 第一行有两个正整数n,k. 接下来是n ...
- 【Unsolved】线性时间选择算法的复杂度证明
线性时间选择算法中,最坏情况仍然可以保持O(n). 原因是通过对中位数的中位数的寻找,保证每次分组后,任意一组包含元素的数量不会大于某个值. 普通的Partition最坏情况下,每次只能排除一个元素, ...
- Android线性布局(Linear Layout)
Android线性布局(Linear Layout) LinearLayout是一个view组(view group),其包含的所有子view都以一个方向排列,垂直或是水平方向.我们能够用androi ...
- 算法线性编程珠玑读书笔记之----->使用线性算法求解连续子序列的最大和
这段时间笔者几篇文章介绍了改算法线性的文章. 关联文章的地址 这个算法我在我的博客里应用动态规划做过,详细实现请参阅我的dp板块,下面给出书上最快的算法,时间复杂度为O(n),称之为线性算法. #in ...
- FastReport.Net使用:[24]其他控件(邮政编码(Zip Code),网格文本(Cellular Text)以及线性刻度尺(Linear Gauge))
邮政编码(Zip Code) Zip Code仅支持数字(0~9) Zip Code支持数据列绑定,表达式,文本等模式 可通过修改SegmentCount属性的值来确定Zip Code的位数. 数字右 ...
随机推荐
- 51nod 1172 Partial Sums V2 卡精度的任意模数FFT
卡精度的任意模数fft模板题……这道题随便写个表就能看出规律来(或者说考虑一下实际意义),反正拿到这题之后,很快就会发现他是任意模数fft模板题.然后我就去网上抄了一下板子……我打的是最土的任意模数f ...
- LoaderManager与CursorLoader用法
一.基本概念 1.LoaderManager LoaderManager用来负责管理与Activity或者Fragment联系起来的一个或多个Loaders对象. 每个Activity或者Fragme ...
- HDU 4303 树形DP
Hourai Jeweled Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 163840/163840 K (Java/Others) ...
- 移动端1px边框问题
用于手机端受dpr的影响,实际开发中,PC端和移动端展示的效果不太一样,往往在PC端显示的是1px,移动端常常是偏粗一些. 解决办法: 主要是用到伪类及缩放.在需要画边框的元素上,设置一个伪类,它的伪 ...
- 整数中1出现的次数(从1到n整数中1出现的次数)
整数中1出现的次数(从1到n整数中1出现的次数) 题目描述 求出1 ~ 13的整数中1出现的次数,并算出100 ~ 1300的整数中1出现的次数?为此他特别数了一下1 ~ 13中包含1的数字有1.10 ...
- 代码Review发现问题
FrmMain.cs中存在问题 1. int i=0 设定为了全局常量且未在类顶部,出现问题时不好查找 i 属于常用临时变量,设定全局变量容易引起混乱 2.定义的全局变量但仅在一处方法中使用,定义全局 ...
- Android 百度定位SDKv4.2及6.0_百度定位实例_安卓定位实例
介绍 由于项目需要.前几天一直在研究百度定位的功能.通过不断的实践终于有结果了.不愿意独享 现在我把我的研究成果和大家分享一下.其实百度的 API 已经相当不错了 这之所以要写出来.一是自己做一个笔记 ...
- Lodash js数据操作库
https://lodash.com/docs/4.17.4
- POJ 3087 Shuffle'm Up DFS
link:http://poj.org/problem?id=3087 题意:给你两串字串(必定偶数长),按照扑克牌那样的洗法(每次从S2堆底中拿第一张,再从S1堆底拿一张放在上面),洗好后的一堆可以 ...
- Sass 基本特性-运算 感觉满满都是坑
Sass中的基本运算 一.加法 在 CSS 中能做运算的,到目前为止仅有 calc() 函数可行.但在 Sass 中,运算只是其基本特性之一. sass做加法运算是可以不考虑参数带单位,但需 ...