第i小的元素

      时间复杂度:O(n).

基本思想:和快速排序的思想相似,也是对数组进行递归划分,但是有所差别的是,快速排序会递归处理划分的两边,而随机化的选择算法只选择一边。

      具体步骤为:首先,随机选择一个数组元素作为主元,从而将数组分解为两个子数组,并得到主元在元素中的位置q,假设较小子数组元素的个数为k-1;然后比较i与k的大小,来确定下一次递归选择哪一边的子数组(注意i的值的改变情况);最后,当i==k时,就求得了第i小的元素。具体实例见图解

具体的程序实现如下:

#include<stdio.h>
#include<stdlib.h>
#include<time.h>

int Partition(int*arrayA,int n,int p,int r);
int RandomPartition(int* arrayA,int n,int p,int r);
int RandomSelect(int* arrayA,int n,int p,int r,int i);

void main()
{
	int arrayA[8]={2,1,3,4,8,6,7,5};
	int n=sizeof(arrayA)/sizeof(int);
	int p=0;
	int r=7;
	int i=4;
	int result=0;
	result=RandomSelect(arrayA,n,p,r,i);
	printf("数组中第%d小的数是%d\n",i,result);

}

/**************************************************\
函数功能:将原数组分成全大于和全小于x的两个子数组
输入:原始数组、要对数组进行操作的起始和结束下标p、r
	  即只对数组指定部分进行操作。
输出:x在数组中的位置
\**************************************************/
int Partition(int*arrayA,int n,int p,int r)
{
	int x=arrayA[r];//使主元x选为数组选中部分的最后一个元素
	int i=p-1;
	int temp=0;
	for(int j=p;j<=r-1;j++)
	{
		if(arrayA[j]<=x)
		{
			i++;
			temp=arrayA[i];
			arrayA[i]=arrayA[j];
			arrayA[j]=temp;
		}
	}
	temp=arrayA[i+1];
	arrayA[i+1]=arrayA[r];
	arrayA[r]=temp;

	return i+1;//最终主元的位置
}

/**************************************************\
函数功能:用随机数确定主元
输入:原始数组、要对数组进行操作的起始和结束下标p、r
	  即只对数组指定部分进行操作
输出:x在数组中的位置
\**************************************************/
int RandomPartition(int* arrayA,int n,int p,int r)
{
	int suiji=0;
	srand(time(0));
	suiji=rand()%(r-p)+p;//产生大于等于p,小于r的随机数
  printf("suiji=%d\n",suiji);
	int temp=0;
	temp=arrayA[r]; //使主元由随机数确定
	arrayA[r]=arrayA[suiji];
	arrayA[suiji]=temp;

	return Partition(arrayA,n,p,r);
}

/**************************************************\
函数功能:找出数组中第i小的数
输入:原始数组、要对数组进行操作的起始和结束下标p、r
	  即只对数组指定部分进行操作
输出:x在数组中的位置
\**************************************************/
int RandomSelect(int* arrayA,int n,int p,int r,int i)
{
	int q=0;

	if(p==r)
		return arrayA[p];

	for(int j=p;j<=r;j++)
		printf("%d ",arrayA[j]);
	printf("\n");
	q=RandomPartition(arrayA,n,p,r);//主元的位置
	printf("gaihou:\n");
	for(int j=p;j<=r;j++)
		printf("%d ",arrayA[j]);
	printf("\n\n");

	int k=q-p+1;
	if(i==k)
		return arrayA[q];
	else if(i<k)
		return RandomSelect(arrayA,n,p,q-1,i);
	else
		return RandomSelect(arrayA,n,q+1,r,i-k);

}

注意:我是在vs2008上运行的,与vc 6.0有点区别,主要是循环体中的循环变量的作用域,出错体现在循环变量的重复定义上。例如:在vs2008或vs2010上,程序为:

#include<stdio.h>

void main()

{

int i=0;

for(int i=0;i<5;i++)

printf("%d ",i);

}

则在VC 6.0上需改为:

#include<stdio.h>

void main()

{

int i=0;

for(i=0;i<5;i++)

printf("%d ",i);

} 

原文:http://blog.csdn.net/tengweitw/article/details/9668849

作者:nineheadedbird

【算法导论】第i小的元素的更多相关文章

  1. 算法导论-顺序统计-快速求第i小的元素

    目录 1.问题的引出-求第i个顺序统计量 2.方法一:以期望线性时间做选择 3.方法二(改进):最坏情况线性时间的选择 4.完整测试代码(c++) 5.参考资料 内容 1.问题的引出-求第i个顺序统计 ...

  2. 《算法导论》——重复元素的随机化快排Optimization For RandomizedQuickSort

    昨天讨论的随机化快排对有重复元素的数组会陷入无限循环.今天带来对其的优化,使其支持重复元素. 只需修改partition函数即可: int partition(int *numArray,int he ...

  3. C++算法导论第九章O(n)期望选择序列第i小的数字

    #include<iostream> #include<vector> #include<algorithm> #include<time.h> usi ...

  4. B树——算法导论(25)

    B树 1. 简介 在之前我们学习了红黑树,今天再学习一种树--B树.它与红黑树有许多类似的地方,比如都是平衡搜索树,但它们在功能和结构上却有较大的差别. 从功能上看,B树是为磁盘或其他存储设备设计的, ...

  5. 红黑树——算法导论(15)

    1. 什么是红黑树 (1) 简介     上一篇我们介绍了基本动态集合操作时间复杂度均为O(h)的二叉搜索树.但遗憾的是,只有当二叉搜索树高度较低时,这些集合操作才会较快:即当树的高度较高(甚至一种极 ...

  6. 堆排序与优先队列——算法导论(7)

    1. 预备知识 (1) 基本概念     如图,(二叉)堆是一个数组,它可以被看成一个近似的完全二叉树.树中的每一个结点对应数组中的一个元素.除了最底层外,该树是完全充满的,而且从左向右填充.堆的数组 ...

  7. 算法导论第十八章 B树

    一.高级数据结构 本章以后到第21章(并查集)隶属于高级数据结构的内容.前面还留了两章:贪心算法和摊还分析,打算后面再来补充.之前的章节讨论的支持动态数据集上的操作,如查找.插入.删除等都是基于简单的 ...

  8. 算法导论----VLSI芯片测试; n个手机中过半是好的,找出哪些是好手机

    对于分治(Divide and Conquer)的题目,最重要是 1.如何将原问题分解为若干个子问题, 2.子问题中是所有的都需要求解,还是选择一部分子问题即可. 还有一点其实非常关键,但是往往会被忽 ...

  9. MIT算法导论——第五讲.Linear Time Sort

    本栏目(Algorithms)下MIT算法导论专题是个人对网易公开课MIT算法导论的学习心得与笔记.所有内容均来自MIT公开课Introduction to Algorithms中Charles E. ...

随机推荐

  1. Java JS SHA-256加密

    http://www.cnblogs.com/elaron/archive/2013/04/09/3010375.html js部分: <html> <head></he ...

  2. Ambari2.6.0 安装HDP2.6.3(离线安装)

    一.下载安装包 因为使用在线安装特别慢,所有的安装包加起来有9个G左右,所以本教程是通过迅雷下载包,然后上传到服务器,通过配置本地源的方式来实现的离线安装.通过ambari安装需要下载下面的三个主要包 ...

  3. android 欢迎界面的制作

    再打开手机app的时候,最先映入我们眼帘的是一个覆盖手机全屏的欢迎界面,在这个界面显示出来的时候整个手机屏幕只会显示这一个界面,上面的标题栏,以及手机最顶端的状态栏都会消失,只有欢迎页面结束跳转到其他 ...

  4. 天梯赛-L1-018. 大笨钟

    L1-018. 大笨钟 时间限制 400 ms 内存限制 65536 kB 代码长度限制 8000 B 判题程序 Standard 作者 陈越 微博上有个自称"大笨钟V"的家伙,每 ...

  5. centos 6安装 H3C iNode 上网客户端

    我的安装目录是/usr/iNode 直接把客户端安装包拷到这个文件夹下然后解压: #rar x iNode2.-R0162.rar 然后进入文件夹,里边有一个install.sh文件,这是一个安装文件 ...

  6. python学习之路前端-jQuery

    jQuery简介      JQuery是继prototype之后又一个优秀的Javascript库.它是轻量级的js库 ,它兼容CSS3,还兼容各种浏览器(IE 6.0+, FF1.5+, Safa ...

  7. Python3 数据结构

    列表 Python中列表是可变的,这是它区别于字符串和元组的最重要的特点,一句话概括即:列表可以修改,而字符串和元组不能. 以下是 Python 中列表的方法: 方法 描述 list.append(x ...

  8. 重载equals方法时要遵守的通用约定--自反性,对称性,传递性,一致性,非空性

    本文涉及到的概念 1.为什么重载equals方法时,要遵守通用约定 2.重载equals方法时,要遵守哪些通用约定   为什么重载equals方法时,要遵守通用约定 Object类的非final方法都 ...

  9. log file sync 等侍值高的一般通用解决办法

    log file sync等待时间发生在redo log从log buffer写入到log file期间. 下面对log file sync做个详细的解释. 何时发生日志写入: 1.commit或者r ...

  10. Android通知Notification全面剖析

    通知 通知是您可以在应用的常规 UI 外部向用户显示的消息.当您告知系统发出通知时,它将先以图标的形式显示在通知区域中.用户可以打开抽屉式通知栏查看通知的详细信息. 通知区域和抽屉式通知栏均是由系统控 ...