[图解算法]线性时间选择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的位数. 数字右 ...
随机推荐
- printf函数用法小记
By francis_hao Aug 26,2017 C语言中printf函数是一个比较常用的函数,但是常用并不代表完全了解,本文翻译了printf的man手册,介绍了其全部功能(不包括ma ...
- android 应用使用Root权限执行linux命令
要让Android应用使用Root权限,首先Android设备必须已经获得Root权限.之后可以通过下面的代码取得process对象. Process process = Runtime.getRun ...
- Aidl实现进程间通信,跨进程回调
aidl支持的文件类型 1. Java 编程语言中的基本类型, 如 int.long.boolean 等, 不需要 import. 2. String.List.Map 和 CharSequence, ...
- 问题03.如果有多个集合的迭代处理情况【使用MAP】
在SQL开发过程中,动态构建In集合条件查询是比较常见的用法,在Mybatis中提供了foreach功能,该功能比较强大,它允许你指定一个集合,声明集合项和索引变量,它们可以用在元素体内.它也允许你指 ...
- 痛苦之旅——安装Eric4
因为想做桌面程序,所以在学PyQt4, 顺便装了下Eric4,这Eric4装起来可不简单,活活花了一个星期..... 网上有很多装Eric4的教程,详细我就不说了,大概步骤是: 1.安装SIP (需要 ...
- UVA 808 Bee Breeding (坐标法)
https://vjudge.net/problem/UVA-808 #include<cmath> #include<cstdio> #include<algorith ...
- [USACO06NOV] Corn Fields
https://www.luogu.org/problem/show?pid=1879 题目描述 Farmer John has purchased a lush new rectangular pa ...
- Tomcat启动报错:org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Catalin
Error starting ApplicationContext. To display the auto-configuration report re-run your application ...
- 【poj2104-求区间第k大数(不修改)】主席树/可持续化线段树
第一道主席树~然而是道比较水的...因为它不用修改... 转载一个让我看懂的主席树的讲解吧:http://blog.csdn.net/regina8023/article/details/419106 ...
- 【NOIP】2016 换教室
[算法]期望DP+floyd [题解]用floyd预处理最短距离. 注意重边与自环——图论双毒!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! QAQ 然后搞清楚方案和概率的问 ...