1. #include <ctime>
  2. #include <iostream>
  3. using namespace std;
  4.  
  5. template <class Type>
  6. void Swap(Type &x,Type &y);
  7.  
  8. inline int Random(int x, int y);
  9.  
  10. template <class Type>
  11. void BubbleSort(Type a[],int p,int r);
  12.  
  13. template <class Type>
  14. int Partition(Type a[],int p,int r,Type x);
  15.  
  16. template <class Type>
  17. Type Select(Type a[],int p,int r,int k);
  18.  
  19. void main()
  20. {
  21. //初始化数组
  22. int a[];
  23.  
  24. //必须放在循环体外面
  25. srand((unsigned)time());
  26.  
  27. for(int i=; i<; i++)
  28. {
  29. a[i] = Random(,);
  30. cout<<"a["<<i<<"]:"<<a[i]<<" ";
  31. }
  32. cout<<endl;
  33.  
  34. cout<<"第23小元素是"<<Select(a,,,)<<endl;
  35.  
  36. //重新排序,对比结果
  37. BubbleSort(a,,);
  38. for(i=; i<; i++)
  39. {
  40. cout<<"a["<<i<<"]:"<<a[i]<<" ";
  41. }
  42. cout<<endl;
  43. }
  44.  
  45. template <class Type>
  46. void Swap(Type &x,Type &y)
  47. {
  48. Type temp = x;
  49. x = y;
  50. y = temp;
  51. }
  52.  
  53. inline int Random(int x, int y)
  54. {
  55. int ran_num = rand() % (y - x) + x;
  56. return ran_num;
  57. }
  58.  
  59. //冒泡排序
  60. template <class Type>
  61. void BubbleSort(Type a[],int p,int r)
  62. {
  63. //记录一次遍历中是否有元素的交换
  64. bool exchange;
  65. for(int i=p; i<r;i++)
  66. {
  67. exchange = false ;
  68. for(int j=; j<=r-i; j++)
  69. {
  70. if(a[j]<a[j-])
  71. {
  72. Swap(a[j],a[j-]);
  73. exchange = true;
  74. }
  75. }
  76. //如果这次遍历没有元素的交换,那么排序结束
  77. if(false == exchange)
  78. {
  79. break ;
  80. }
  81. }
  82. }
  83.  
  84. template <class Type>
  85. int Partition(Type a[],int p,int r,Type x)
  86. {
  87. int i = p-,j = r + ;
  88.  
  89. while(true)
  90. {
  91. while(a[++i]<x && i<r);
  92. while(a[--j]>x);
  93. if(i>=j)
  94. {
  95. break;
  96. }
  97. Swap(a[i],a[j]);
  98. }
  99. return j;
  100. }
  101.  
  102. template <class Type>
  103. Type Select(Type a[],int p,int r,int k)
  104. {
  105. if(r-p<)
  106. {
  107. BubbleSort(a,p,r);
  108. return a[p+k-];
  109. }
  110. //(r-p-4)/5相当于n-5
  111. for(int i=; i<=(r-p-)/; i++)
  112. {
  113. //将元素每5个分成一组,分别排序,并将该组中位数与a[p+i]交换位置
  114. //使所有中位数都排列在数组最左侧,以便进一步查找中位数的中位数
  115. BubbleSort(a,p+*i,p+*i+);
  116. Swap(a[p+*i+],a[p+i]);
  117. }
  118. //找中位数的中位数
  119. Type x = Select(a,p,p+(r-p-)/,(r-p-)/);
  120. i = Partition(a,p,r,x);
  121. int j = i-p+;
  122. if(k<=j)
  123. {
  124. return Select(a,p,i,k);
  125. }
  126. else
  127. {
  128. return Select(a,i+,r,k-j);
  129. }
  130. }

提醒:此篇需要先理解快速排序。

[图解+例子]

一、建立随机数组

(共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——<递归与分治策略>的更多相关文章

  1. 递归与分治策略之循环赛日程表Java实现

    递归与分治策略之循环赛日程表 一.问题描述 设有n=2^k个运动员要进行网球循环赛.现要设计一个满足以下要求的比赛日程表: (1)每个选手必须与其他n-1个选手各赛一次: (2)每个选手一天只能参赛一 ...

  2. 递归与分治策略之棋盘覆盖Java实现

    递归与分治策略之棋盘覆盖 一.问题描述 二.过程详解 1.棋盘如下图,其中有一特殊方格:16*16 . 2.第一个分割结果:8*8 3.第二次分割结果:4*4 4.第三次分割结果:2*2 5.第四次分 ...

  3. [图解算法] 归并排序MergeSort——<递归与分治策略>

    #include"iostream.h" void Merge(int c[],int d[],int l,int m,int r){ ,k=l; while((i<=m)& ...

  4. [图解算法] 二分查找Binary-Search——<递归与分治策略>

    #include"iostream.h" int BinarySearch(int a[],int left,int right,const int& x) { if(le ...

  5. 算法:线性时间选择(C/C++)

    Description 给定线性序集中n个元素和一个整数k,n<=2000000,1<=k<=n,要求找出这n个元素中第k小的数. Input 第一行有两个正整数n,k. 接下来是n ...

  6. 【Unsolved】线性时间选择算法的复杂度证明

    线性时间选择算法中,最坏情况仍然可以保持O(n). 原因是通过对中位数的中位数的寻找,保证每次分组后,任意一组包含元素的数量不会大于某个值. 普通的Partition最坏情况下,每次只能排除一个元素, ...

  7. Android线性布局(Linear Layout)

    Android线性布局(Linear Layout) LinearLayout是一个view组(view group),其包含的所有子view都以一个方向排列,垂直或是水平方向.我们能够用androi ...

  8. 算法线性编程珠玑读书笔记之----->使用线性算法求解连续子序列的最大和

    这段时间笔者几篇文章介绍了改算法线性的文章. 关联文章的地址 这个算法我在我的博客里应用动态规划做过,详细实现请参阅我的dp板块,下面给出书上最快的算法,时间复杂度为O(n),称之为线性算法. #in ...

  9. FastReport.Net使用:[24]其他控件(邮政编码(Zip Code),网格文本(Cellular Text)以及线性刻度尺(Linear Gauge))

    邮政编码(Zip Code) Zip Code仅支持数字(0~9) Zip Code支持数据列绑定,表达式,文本等模式 可通过修改SegmentCount属性的值来确定Zip Code的位数. 数字右 ...

随机推荐

  1. 51nod 1172 Partial Sums V2 卡精度的任意模数FFT

    卡精度的任意模数fft模板题……这道题随便写个表就能看出规律来(或者说考虑一下实际意义),反正拿到这题之后,很快就会发现他是任意模数fft模板题.然后我就去网上抄了一下板子……我打的是最土的任意模数f ...

  2. LoaderManager与CursorLoader用法

    一.基本概念 1.LoaderManager LoaderManager用来负责管理与Activity或者Fragment联系起来的一个或多个Loaders对象. 每个Activity或者Fragme ...

  3. HDU 4303 树形DP

    Hourai Jeweled Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 163840/163840 K (Java/Others) ...

  4. 移动端1px边框问题

    用于手机端受dpr的影响,实际开发中,PC端和移动端展示的效果不太一样,往往在PC端显示的是1px,移动端常常是偏粗一些. 解决办法: 主要是用到伪类及缩放.在需要画边框的元素上,设置一个伪类,它的伪 ...

  5. 整数中1出现的次数(从1到n整数中1出现的次数)

    整数中1出现的次数(从1到n整数中1出现的次数) 题目描述 求出1 ~ 13的整数中1出现的次数,并算出100 ~ 1300的整数中1出现的次数?为此他特别数了一下1 ~ 13中包含1的数字有1.10 ...

  6. 代码Review发现问题

    FrmMain.cs中存在问题 1. int i=0 设定为了全局常量且未在类顶部,出现问题时不好查找 i 属于常用临时变量,设定全局变量容易引起混乱 2.定义的全局变量但仅在一处方法中使用,定义全局 ...

  7. Android 百度定位SDKv4.2及6.0_百度定位实例_安卓定位实例

    介绍 由于项目需要.前几天一直在研究百度定位的功能.通过不断的实践终于有结果了.不愿意独享 现在我把我的研究成果和大家分享一下.其实百度的 API 已经相当不错了 这之所以要写出来.一是自己做一个笔记 ...

  8. Lodash js数据操作库

    https://lodash.com/docs/4.17.4

  9. POJ 3087 Shuffle'm Up DFS

    link:http://poj.org/problem?id=3087 题意:给你两串字串(必定偶数长),按照扑克牌那样的洗法(每次从S2堆底中拿第一张,再从S1堆底拿一张放在上面),洗好后的一堆可以 ...

  10. Sass 基本特性-运算 感觉满满都是坑

    Sass中的基本运算 一.加法 在 CSS 中能做运算的,到目前为止仅有 calc() 函数可行.但在 Sass 中,运算只是其基本特性之一.      sass做加法运算是可以不考虑参数带单位,但需 ...