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

  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. shell中的颜色显示

    By francis_hao    Sep 30,2017   图片来自参考[1]     其中,"033"是八进制数,其对应的asciima也就是ESC.后面的颜色格式为:[背景 ...

  2. Android 解决adb server is out of date. killing... ADB server didn't ACK * failed to star

    The connection to adb is down, and a severe error has occured. [-- :: - HelloOPone] You must restart ...

  3. java有关Time类型数据的接收和转换

    一:前言 有关Time的时间其实很少有用到.但是用到就很纠结了,转换和保存,都是烦人的事情,我自己就在这上面吃过一个亏,所以就加载下来吧! 二:内容 (1):被坑的地方 实体类 import java ...

  4. maven中package和install命令的区别

    mvn package 编译并打包工程,根据pom文件中packaging是jar还是war进行打包,会在项目的target目录下生成一个jar/war包. mvn install 打包并安装到mav ...

  5. 数据结构:Rope

    以BZOJ1507为例,这里仅仅展示动态区间问题的一些典型操作,包括插入删除和修改,查询的话不支持按顺序查询 使用起来很简单很方便 #include<cstdio> #include< ...

  6. CSUST选拔赛题解

    本鶸鸡于本月10号参加了蔽校的选拔赛,成绩差的死,大部分的题都是赛后花了好长时间才补出来的,其中有些题还是靠QAQorz大佬帮忙才能解决,感谢Qls对我的帮助~接下来就附带上我的暴力题解,大佬们有更好 ...

  7. HDU 1180 诡异的楼梯 (广搜)

    题目链接 Problem Description Hogwarts正式开学以后,Harry发现在Hogwarts里,某些楼梯并不是静止不动的,相反,他们每隔一分钟就变动一次方向. 比如下面的例子里,一 ...

  8. HDU 2059 龟兔赛跑 (dp)

    题目链接 Problem Description 据说在很久很久以前,可怜的兔子经历了人生中最大的打击--赛跑输给乌龟后,心中郁闷,发誓要报仇雪恨,于是躲进了杭州下沙某农业园卧薪尝胆潜心修炼,终于练成 ...

  9. MSSQL DBOtherSQL

    --------------------------查询表中的数据------------------------------ --1.请查询出MyStudent表中的所有数据 --下面的语句表示查询 ...

  10. Winform GDI+

    什么是GDI+ GDI (Graphics Device Interface), 是属于绘图方面的 API (Application Programming Interface). 因为应用程序不能直 ...