第5章:概率分析与随机算法
2016-05-19 21:39
211 查看
知识点总结
概率分析是在问题分析中应用概率的理念,必须要假设输入的分布,然后计算出一个平均情形下的运行时间,其中对所有可能的输入分布取平均值,得到的这种运行时间称为平均情况运行时间如果一个算法的行为不仅由输入决定,而且也由随机数生成器产生的数值决定,我们称这个算法是随机的。当分析一个随机算法的运行时间时,我们以运行时间的期望值来衡量,其中输入值由随机数生成器产生,我们称为期望运行时间。
当我们在概率分析时,是假设输入具有某种分布。但是在分析随机算法时,我们能通过该算法内部的随机数生成器产生我们想要的输入分布。也就是说在概率分析时,具有某种输入的分布是虚拟的,是人为假设的;但是对于随机算法来说,具有某种输入的分布是真真实实的,可以人为得到的。因此为了便于区分,我们将概率分析时得到的平均时间称之为平均情况运行时间,但是对于随机算法来说,我们将得到的平均时间称之为期望运行时间,有点细微差别。
指示器随机变量: 给定一个样本空间S和一个事件A,那么事件A对应的指示器随机变量 I{A} 定义为:I{A}=1(如果A发生);I{A}=0 (如果A不发生)。因此I{A}的期望值E[I{A}]=1*Pr{A发生}+0 *Pr{A不发生}=Pr{A发生}。具体应用例子可以看5.2-4和5.2-5
算法或例子代码
我列举了随机数组排列,周期循环的随机数组排列和数组中一个子集的随机排列这三种算法代码。随机数组排列:
~~~c++
#include
#include
using namespace std;
template<class Type> void randomPermuteArray(vector<Type>& array) { if(array.size()==0){ cout<<"The array is empty?!"<<endl; return; } for(int i=0;i!=array.size();++i) { // random number in the range between i and the end of the array int randomPosition=rand()%(array.size()-i)+i; swap(array[i],array[randomPosition]); } }
~~~
该算法可以理解为在箱子里面有n个不同的小球,现在从箱子里面不放回的拿小球,一共有 n! 中取法,那么取到一种特定的n个球的组合概率为 1/(n!)。
周期循环的随机数组排列
假设有一个数组为{1,2,3,4,5},周期循环的随机数组可以为{2,3,4,5,1},{3,4,5,1,2}等等,也就是说原数组中每一个元素偏移一个固定的量,但这固定的量是随机的。
#include <vector> #include <cstdlib> using namespace std; template<class Type> void cyclicRandomPermuateArray(const vector<Type>& array,vector<Type>& resultArray) { if(array.size()==0){ cout<<"The array is empty()?!"<<endl; return; } resultArray.clear(); resultArray.resize(array.size()); // to porduce a random offset int offset=rand()%array.size(); for(int i=0;i!=array.size();++i) { int dest=offset+i; if(dest>array.size()-1) dest-=array.size(); resultArray[dest]=array[i]; } }
数组中一个子集的随机排列
假设有一个n维数组,现在不需要产生整个数组的随机排列,而只是想要产生其中m(m
#include <vector> #include <cstdlib> using namespace std bool isBelong(const Type& val,const vector<Type> 4000 & array) { if(array.size()==0) return false; for(int i=0;i!=array.size();++i) if(val==array[i]) return true; return false; } template<class Type> void randomSubArrayRec(int subsetNumber,int rightEnd,vector<Type>& resultSubArray) { if(subsetNumber==0) return; randomSubArrayRec(subsetNumber-1,rightEnd-1, resultSubArray); int randomPosition=rand()%(rightEnd+1); if(isBelong(randomPosition,resultSubArray)) // the elements in array have to be different from each other. resultSubArray.push_back(rightEnd); else resultSubArray.push_back(randomPosition); } template<class Type> void randomSubArray(int subsetNumber,const vector<Type>& array, vector<Type>& resultSubArray) { if(array.size()==0){ cout<<"The array is empty?!"<<endl; return; } if(subsetNumber>array.size()){ cout<<"Please verify the number of subset!"<<endl; return; } vector<int> randomArrayPosition; // a random subset of element positions not element itself! randomSubArrayRec(subsetNumber,array.size()-1, randomArrayPosition); resultSubArray.clear(); for(int i=0;i!=subsetNumber;++i) resultSubArray.push_back(array[randomArrayPosition[i]]); }
在上面的算法中,我们首先产生了元素位置的随机子集,而不是直接产生元素本身的随机子集,因此上述程序第26行要求用于产生随机子集的数组不能有相同的元素。既然产生了元素位置的随机集合并且元素位置对应一个元素,因此也就产生了一个子集的随机元素集合。
相关文章推荐
- 树状数组
- Mybatis中运用小技巧(一)
- Elsevier LaTeX instructions 排版指导
- 输出乘法口诀表
- winform学习-----理解小概念-20160518
- JS闭包之深刻理解
- MySQL入门--查看当前的mysql客户端版本号、当前系统时间、登陆的用户
- 开发还是算法,一直困惑我的问题
- 字符串初始化的方式
- 线上遇到插入重复数据(重复提交)
- SCI期刊分区七问
- 异或和同或
- 磁盘映射
- [Redis] redis-cli 命令总结
- string类应用举例
- Android ORMLite额框架
- <<深入Java虚拟机>>-虚拟机类加载机制-学习笔记
- 简单了解json以及使用google json 2.2
- BlockingQueue深入分析
- 排序算法总结