c_cpp 【随机化算法】线性时间选择算法【7.3.1】舍伍德(舍伍德)算法

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了c_cpp 【随机化算法】线性时间选择算法【7.3.1】舍伍德(舍伍德)算法相关的知识,希望对你有一定的参考价值。

//随机化算法 线性时间选择 随机划分选择基准
#include "stdafx.h"
#include "RandomNumber.h"
#include <iostream>
using namespace std;
 
template<class Type>
Type select(Type a[],int l,int r,int k);
 
template<class Type>
Type select(Type a[],int n,int k);
 
template <class Type>
inline void Swap(Type &a,Type &b);
 
int main()
{
	int a[] = {5,7,3,4,8,6,9,1,2};  
	cout<<"原数组为:"<<endl;
	for(int i=0; i<9; i++)  
    {  
        cout<<a[i]<<" ";  
    }  
    cout<<endl;  
	cout<<"所给数组第7小元素为:"<<select(a,9,7)<<endl;  
	return 0;
}
 
//计算a[0:n-1]中第k小元素
//假设a[n]是一个键值无穷大的元素
template<class Type>
Type select(Type a[],int n,int k)
{
	if(k<1 || k>n)
	{
		cout<<"请输入正确的k!"<<endl;
		return 0;
	}
	return select(a,0,n-1,k);
}
 
//计算a[l:r]中第k小元素
template<class Type>
Type select(Type a[],int l,int r,int k)
{
	static RandomNumber rnd;
	while(true)
	{
		if(l>=r)
		{
			return a[l];
		}
 
		int i = l,
			j = l + rnd.Random(r-l+1);//随机选择划分基准
 
		Swap(a[i],a[j]);
 
		j = r+1;
		Type pivot = a[l];
 
		//以划分基准为轴做元素交换
		while(true)
		{
			while(a[++i]<pivot);
			while(a[--j]>pivot);
			if(i>=j)
			{
				break;
			}
			Swap(a[i],a[j]);
		}
 
		if(j-l+1 == k)//第k小
		{
			return pivot;
		}
 
		//a[j]必然小于pivot,做最后一次交换,满足左侧比pivot小,右侧比pivot大
		a[l] = a[j];
		a[j] = pivot;
 
		//对子数组重复划分过程
		if(j-l+1<k)
		{
			k = k-j+l-1;//右侧:k-(j-l+1)=k-j+l-1
			l = j + 1;
		}
		else
		{
			r = j - 1;
		}
	}
}
 
template <class Type>
inline void Swap(Type &a,Type &b)
{
	Type temp = a;
	a = b;
	b = temp;
}
//随机化算法 线性时间选择 输入预处理,洗牌
#include "stdafx.h"
#include "RandomNumber.h"
#include <iostream>
using namespace std;
 
template<class Type>
Type select(Type a[],int l,int r,int k);
 
template<class Type>
Type select(Type a[],int n,int k);
 
template<class Type>
void Shuffle(Type a[],int n);
 
template <class Type>
inline void Swap(Type &a,Type &b);
 
int main()
{
	int a[] = {5,7,3,4,8,6,9,1,2};  
	cout<<"原数组为:"<<endl;
	for(int i=0; i<9; i++)  
    {  
        cout<<a[i]<<" ";  
    }  
	cout<<endl; 
	Shuffle(a,9);//洗牌
	cout<<"洗牌后数组为:"<<endl;
	for(int i=0; i<9; i++)  
    {  
        cout<<a[i]<<" ";  
    }  
    cout<<endl;  
	cout<<"所给数组第7小元素为:"<<select(a,9,7)<<endl;  
	return 0;
}
 
//计算a[0:n-1]中第k小元素
//假设a[n]是一个键值无穷大的元素
template<class Type>
Type select(Type a[],int n,int k)
{
	if(k<1 || k>n)
	{
		cout<<"请输入正确的k!"<<endl;
		return 0;
	}
	return select(a,0,n-1,k);
}
 
//计算a[l:r]中第k小元素
template<class Type>
Type select(Type a[],int l,int r,int k)
{
	while(true)
	{
		if(l>=r)
		{
			return a[l];
		}
		int i = l;
		int j = r+1;
		Type pivot = a[l];
 
		//以划分基准为轴做元素交换
		while(true)
		{
			while(a[++i]<pivot);
			while(a[--j]>pivot);
			if(i>=j)
			{
				break;
			}
			Swap(a[i],a[j]);
		}
 
		if(j-l+1 == k)//第k小
		{
			return pivot;
		}
 
		//a[j]必然小于pivot,做最后一次交换,满足左侧比pivot小,右侧比pivot大
		a[l] = a[j];
		a[j] = pivot;
 
		//对子数组重复划分过程
		if(j-l+1<k)
		{
			k = k-j+l-1;//右侧:k-(j-l+1)=k-j+l-1
			l = j + 1;
		}
		else
		{
			r = j - 1;
		}
	}
}
 
template <class Type>
inline void Swap(Type &a,Type &b)
{
	Type temp = a;
	a = b;
	b = temp;
}
 
//随机洗牌算法
template<class Type>
void Shuffle(Type a[],int n)
{
	static RandomNumber rnd;
	for(int i=0; i<n; i++)
	{
		int j = rnd.Random(n-i)+i;
		Swap(a[i],a[j]);
	}
}

以上是关于c_cpp 【随机化算法】线性时间选择算法【7.3.1】舍伍德(舍伍德)算法的主要内容,如果未能解决你的问题,请参考以下文章

c_cpp 【随机化算法】随机数【7.1】

c_cpp 【随机化算法】跳跃表【7.3.3】舍伍德(舍伍德)算法

c_cpp 【随机化算法】素数测试【7.5.3】蒙特卡罗(Monte Carlo)算法

c_cpp 【随机化算法】搜索有序表【7.3.2】舍伍德(舍伍德)算法

c_cpp 【随机化算法】计算定积分【7.2.2】

c_cpp 【随机化算法】计算π值【7.2.1】