获得顺序统计量的选择算法(数组中第i顺序的元素)

假设数组是互异的,选择算法获得数组中的顺序统计量,期望时间为O(n),最坏时间为O(n平方)

算法有一些与快速排序相似,对数组选定参考元素左右分类以后,左边是小于参考元素reference的,右边是大于reference的,然后检查一下reference的位置,是i就对了,不是i就递归调用。同样可以通过数组随机重排来达到平均期望时间

 
//获得顺序统计量的选择算法
#include <iostream>
#include <time.h>
#include <stdlib.h>
#define N 10

using namespace std;
void Swap(int &a,int &b);
int RandLeftRight(int left,int right);//产生left到right的随机数
int RandPartition(int a[],int left,int right);随机选取元素进行left到right数组原址重排 
int Partition(int a[],int left,int right);//对a数组分类,返回参考元素索引,左边的小于参考元素,右边的大于参考元素

int RandSelect(int a[],int left,int right,int i);//返回数组中排第i个位置的元素,(从小往大数i) 

int main()
{
	int a[N] = {9,5,1,4,4,2,3,6,10,7};
	cout<<RandSelect(a,0,N-1,4)<<endl;
} 

inline void Swap(int &a,int &b)
{
	int temp;
	temp = a;
	a = b;
	b = temp;
}

int RandLeftRight(int left,int right)//left,right是索引,所以应该产生left到right包括left,right的随机数 
{
	srand((unsigned)time(NULL));
	return rand()%(right-left+1)+left;
}

int Partition(int a[],int left,int right)//子数组原址重排,把下面的粘贴上来的的 
{
	int reference = a[right];
	int index_left = left,index_right = right;
		while(index_left!= index_right)
	{
		while(index_left!=index_right)//两个索引没到一起的话
		{
			if(a[index_left]>reference) break;//找找到了应该往右放的数
			index_left++;//没找到就继续往右搜索 
		}
		while(index_left!=index_right)
		{
			if(a[index_right]<reference) break;
			index_right--;
		} 
		Swap(a[index_left],a[index_right]); 

	}
	Swap(a[index_left],a[right]); 
	return index_left;//返回最后这个参考元素的索引 
}

int RandPartition(int a[],int left,int right)//随机选取元素进行子数组原址重排 
{
	int i = RandLeftRight(left,right);
	Swap(a[i],a[right]);
	return Partition(a,left,right);
} 

int RandSelect(int a[],int left,int right,int i)
{
	if(left == right)
		return a[left];
	int q = RandPartition(a,left,right);
	int len_left = q-left+1;
	if(len_left == i) return a[q];
	else if(len_left>i) return RandSelect(a,left,q-1,i);
	else return RandSelect(a,q+1,right,i-len_left);
}

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值