【算法导论】第i小的元素

简介: 第i小的元素       时间复杂度:O(n).       基本思想:和快速排序的思想相似,也是对数组进行递归划分,但是有所差别的是,快速排序会递归处理划分的两边,而随机化的选择算法只选择一边。

第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

目录
相关文章
|
6月前
|
算法 Java
[Java·算法·简单] LeetCode 27. 移除元素 详细解读
[Java·算法·简单] LeetCode 27. 移除元素 详细解读
47 1
|
12天前
|
存储 算法 Java
解析HashSet的工作原理,揭示Set如何利用哈希算法和equals()方法确保元素唯一性,并通过示例代码展示了其“无重复”特性的具体应用
在Java中,Set接口以其独特的“无重复”特性脱颖而出。本文通过解析HashSet的工作原理,揭示Set如何利用哈希算法和equals()方法确保元素唯一性,并通过示例代码展示了其“无重复”特性的具体应用。
30 3
|
3月前
|
算法
【算法】二分查找——在排序数组中查找元素的第一个和最后一个位置
【算法】二分查找——在排序数组中查找元素的第一个和最后一个位置
|
13天前
|
存储 算法 Java
Set接口及其主要实现类(如HashSet、TreeSet)如何通过特定数据结构和算法确保元素唯一性
Java Set因其“无重复”特性在集合框架中独树一帜。本文解析了Set接口及其主要实现类(如HashSet、TreeSet)如何通过特定数据结构和算法确保元素唯一性,并提供了最佳实践建议,包括选择合适的Set实现类和正确实现自定义对象的hashCode()与equals()方法。
29 4
|
5月前
|
算法
数据结构和算法学习记录——习题-移除链表元素
数据结构和算法学习记录——习题-移除链表元素
24 0
|
5月前
|
存储 算法 Java
Java查找算法概览:二分查找适用于有序数组,通过比较中间元素缩小搜索范围;哈希查找利用哈希函数快速定位,示例中使用HashMap存储键值对,支持多值关联。
【6月更文挑战第21天】Java查找算法概览:二分查找适用于有序数组,通过比较中间元素缩小搜索范围;哈希查找利用哈希函数快速定位,示例中使用HashMap存储键值对,支持多值关联。简单哈希表实现未涵盖冲突解决和删除操作。
51 1
|
5月前
|
算法
【经典LeetCode算法题目专栏分类】【第10期】排序问题、股票问题与TOP K问题:翻转对、买卖股票最佳时机、数组中第K个最大/最小元素
【经典LeetCode算法题目专栏分类】【第10期】排序问题、股票问题与TOP K问题:翻转对、买卖股票最佳时机、数组中第K个最大/最小元素
|
5月前
|
算法 搜索推荐 Java
【经典算法】LeetCode 215. 数组中的第K个最大元素(Java/C/Python3实现含注释说明,Medium)
【经典算法】LeetCode 215. 数组中的第K个最大元素(Java/C/Python3实现含注释说明,Medium)
41 3
|
5月前
|
算法
【数据结构与算法 刷题系列】移除链表元素
【数据结构与算法 刷题系列】移除链表元素
|
5月前
|
算法
数据结构和算法学习记录——认识二叉搜索树及二叉搜索树的查找操作(递归以及迭代实现-查找操作、查找最大和最小元素)
数据结构和算法学习记录——认识二叉搜索树及二叉搜索树的查找操作(递归以及迭代实现-查找操作、查找最大和最小元素)
48 0