基本特征
对所求解问题的同一实例用同一随机化算法求解两次可能得到完全不同的效果(不确定的算法)
大致内容
数值化随机算法
求解数值问题的近似解,时间越长,精度越高
蒙特卡罗算法
求解准确解(不一定正确),时间越长,得到正确解的概率越大
拉斯维加斯算法
可能找不到解,但一旦找到解一定是正确的,时间越长,找到解的概率越大
舍伍德算法
总能找到解,且一定是正确的
预备内容
1.随机数
计算机只能产生伪随机数,最常用的方法是线性同余法
a0=d(d≥m)
an=(ban-1+c) mod m(b≥0,c≥0)
随机序列的种子d
2.产生随机数的代码
需要的内容:随机数类+用户初始化种子(randSeed/无符号整型或者由系统时间产生)
//随机数类
const unsigned long maxshort=65536L;
const unsigned long multiplier=1194211693L;
const unsigned long adder=12345L;
class RandomNumber{
private:
unsigned long randSeed;
public:
RandomNumber(unsigned long s=0);//构造函数,0表示系统时间产生种子
unsigned short Random(unsigned long n);//产生0:n-1的随机整数
double fRandom(void);//产生(0-1)随机实数
};
RandomNumber::RandomNumber(unsigned long s){
if(s==0)
randSeed=time(0);
else
randSeed=s;//产生种子
}
unsigned short RandomNumber::Random(unsigned long n){
randSeed=multiplier*randSeed + adder;//见上方an定义
return (unsigned short)((randSeed>>16)%n);
//因为randSeed较高的16位随机性比较好,所以选择16,可以修改
}
double RandomNumber::fRandom(void){
return Random(maxshort)/double(maxshort);
//利用Random产生一个比maxshort小的整数,再除以maxshort得到0-1之间实数
}
算法的实例和描述
1.数值化算法
eg1.计算pi
思路:
向半径为r的圆及其外切正方形内随机投点,(次数足够多时)落在圆内的几率是pi/4,推出pi≈4k/n
eg2.计算定积分
思路:
1)随机投点法

在0-1的方格中随机投点,投到G区的概率×总面积即为积分大小
对于在a-b内积分的形式,做代换换到0-1内即可
x=a+(b-a)z,用z替换积分号中的x使得积分范围0-1
最大值最小值缩到0-1内(拉伸),将积分换成I*=c*I+d形式
2)平均值法
//再补充太麻烦了不想看…
2.舍伍德算法
目的:消除算法所需时间与输入实例的联系
使得对任何输入规模为n的序列,算法A所需的时间总是平均时间t(A)+s(n)
eg1.线性时间选择算法的随机化版本
改变:随机的选择一个数组元素作为划分基准
//改变部分的代码
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);//j为[l,r]之中的随机一个数
swap(a[i],a[j]);
j=r+1;
Type pivot=a[l];//划分基准为之前随机选的a[j]
}
...
}
eg2.搜索有序表
1)有序表结构
value数组:记录值
link:记录每个元素后继元素的下标
2)随机的部分
搜索值为x的元素:随机抽取数组元素,在较接近x的位置开始做顺序搜索
插入值为x的元素:搜索(确定值为x的元素不在其中)+存储在value[n+1]中修改指针
删除元素k:搜索+前驱元素修改指针+搜索最大元素填补删除后的空洞
eg3.跳跃表(有序的链表)
目的:利用舍伍德算法随机的特性,对有序链表进行改造(附加向前指针/可以跳过某些结点搜索)
级别:某个结点拥有k+1个指针,则这个结点是k级结点
特点:
1)具有i级指针的结点中同时具有i+1级指针所占比例约为p
搜索:略
插入:
1)找插入位置
2)随机生成新插入结点级别
+初始化为0
+随机数生成器反复生成在[0,1)的随机实数q
+q<p则级别增加1,反复步骤2-3直到q>=p
+规定新节点级别上界
删除:
1)搜索k,找到则删除,并把该元素放在e中,没找到则引发异常
3.拉斯维加斯算法
特点:
1)可能找不到解,因此使用bool型表示是否找到解
2)反复调用搜索解
eg1.n后问题
思路:随机放皇后(只要和前一个皇后不冲突就可以放)
eg2.整数因子分解
可找到0-x2的整数因子分割
//尝试法
int split(int n){
int m=(int)(sqrt(double(n)));//找到根号n的位置
for(int i=2;i<=m;i++){
if(n%i==0)
return i;
}
return 1;
}
Pollard算法:相同时间找到0-x4的因子分解
int gcd(int a,int b){
if(b==0)
return a;
else
return gcd(b,a%b);
}//计算最大公约数
void Pollard(int n){
RandomNumber rnd;
int i=1;
int x=rnd.Random(n);//随机整数
int y=x;
int k=2;
while(true){
i++;
x=(x*x-1)%n;
int d=gcd(y-x,n);//求n的非平凡因子
if((d>1)&&(d<n))
cout<<d<<endl;//总能找到
if(i==k){
y=x;
k*=2;
}
}
}
3.蒙特卡罗算法
1)名词:
优势:蒙特卡罗算法得到正确解的概率不小于p(算法是p正确的),p-1/2称作优势
偏真算法:返回true时解一定正确,返回false时解可能错误
2)实例
eg.素数测试
Wilson定理:(n-1)!≡-1(mod n)
对应算法:计算量过大难以实现
费马小定理(必要条件):如果是一个素数p,且有0<a<p,则ap-1≡1(mod p)*
对应算法:计算d=2n-1mod n来判断素性
可能出现的错误:某些少量的满足费马小定理的合数(Carmichael数)
二次探测定理:如果p是一个素数,且0<x<p,则方程的解x2≡1(mod p)的解为x=1,x=p-1(改进使用费马小定理的算法)
算法power:费马小定理+二次探测定理
void power(unsigned int a,unsigned int p,unsigned int n,unsigned int&result,bool &composite){
unsigned int x;//存储result的结果
if(p==0)
result=1;
else{
power(a,p/2,n,x,composite);//递归计算
result=(x*x)%n;//二次探测
if((result==1)&&(x!=1)&&(x!=n-1))
composite=1;//二次探测后筛除误判的部分
if((p%2)==1)
result=(result*a)%n;
}
}
bool Prime(unsigned int n){
RandomNumber rnd;
unsigned int a,result;
bool composite=false;
a=rnd.Random(n-3)+2;
power(a,n-1,n,result,composite);
if(composite||(result!=1))
return false;
else
return true;
}
//代码片均来源于《计算机算法设计与分析(第5版)》,作者:王晓东
//大致整理了一下(我也是萌新啊),不是很详细,可能有很多错误,如有错误望各位指正,感谢!
本文介绍了随机化算法的四大类型:数值化随机算法、蒙特卡罗算法、拉斯维加斯算法和舍伍德算法,详细阐述了每种算法的特点、应用场景及其实现方式,包括计算π、定积分、线性时间选择算法、有序表搜索、跳跃表、n后问题、整数因子分解、素数测试等实例。

2282

被折叠的 条评论
为什么被折叠?



