Shuffle-洗牌算法
2021/12/2 13:06:33
本文主要是介绍Shuffle-洗牌算法,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
顾名思义:Shuffle算法,叫做洗牌算法,它的目标正好与各种的sort算法相反,即把一个有序(或者无序)的一系列元素打乱。
举个两例子
1、大家都知道扑克牌,我们每次都需要在摸牌之前把牌洗掉,用来让每个人摸到每张牌的概率尽量相等,增加游戏的随机性和乐趣;
2、还有音频播放器,有一些人不喜欢顺序播放,而喜欢使用随机播放(其实随机播放分为两种,random和shuffle,后文会介绍到),比如iPod Shuffle的卖点之一就是“你永远不知道你将要听到的下一首歌曲是什么”。
至少,如果要模拟扑克牌游戏,或者做音频播放器,都要使用shuffle算法,而二者的shuffle算法却有一些区别,一个是一次性的洗牌,另一个则是每次取一首歌。那么怎么实现他们呢?
<? //SortHelper排序帮助类,这里只截取一个在下文用到的函数 class SortHelper{ //交换两个数组元素 public static function swap(&$arr, $l, $j) { $temp = $arr[$l]; $arr[$l] = $arr[$j]; $arr[$j] = $temp; } }
ShuffleExp洗牌算法
/** * ShuffleExp洗牌算法 * 洗牌算法实际上就是常见的随机问题。我们可以抽象理解为:得到一个M以内的所有自然数的随机顺序数组。 * 好的洗牌算法保证每一次的概率都基本一样 * */ class ShuffleExpRun{ public $N; public $n; public $m; public function __construct($N, $n, $m) { $this->N = $N; $this->n = $n; $this->m = $m; } /** * 洗牌算法 - 自证函数主入口 * * 构建数据 * 计算概率 * 输出概率值 */ function ShuffleExpRun() { $freq = $arr = []; for ($i = 0; $i < $this->N; $i++) { //构建数据 $this->reset($arr); //洗牌算法 $this->shuffle($arr); //统计每一位的总数量 for ($j = 0; $j < $this->n; $j++) { $freq[$j] += $arr[$j]; } } //计算概率并输出 for ($i=0; $i < $this->n; $i++) { echo $i. ":". floatval($freq[$i] / $this->N) . "\n"; } } /** * 构建数据 */ public function reset(&$arr) { //默认 for ($i = 0; $i < $this->m; $i++) { $arr[$i] = 1; } for ($i = $this->m; $i < $this->n; $i++) { $arr[$i] = 0; } } /** * 洗牌算法 - 可单独使用此函数 - 放到这里是为了自证此函数真的是等概率算法 * 从后往前排 * 总数组长度 n, 初始化用 n - 1(因为数组索引从0开始) * 每次从 [0, i+1) 区间里随机选择一个元素和 i 位置的进行交换 */ public function shuffle(&$arr) { for ($i = $this->n - 1; $i >= 0; $i--) { //从 [0, i+1) 区间里随机选择一个元素 $x = intval($this->randomFloat() * ($i+1)); SortHelper::swap($arr, $i, $x); } } /** * 辅助函数 * 生成 min - max 之间的随机数(float)带小数 * 如果都不传,默认生成 0 - 1 之间的随机数 * */ function randomFloat($min = 0, $max = 1) { return $min + mt_rand() / mt_getrandmax() * ($max - $min); } } $shuff = new ShuffleExpRun(100000,10,5); $shuff->ShuffleExpRun();
概率分布
执行后可以看到概率分布
这篇关于Shuffle-洗牌算法的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-11-24Java中定时任务实现方式及源码剖析
- 2024-11-24Java中定时任务实现方式及源码剖析
- 2024-11-24鸿蒙原生开发手记:03-元服务开发全流程(开发元服务,只需要看这一篇文章)
- 2024-11-24细说敏捷:敏捷四会之每日站会
- 2024-11-23Springboot应用的多环境打包入门
- 2024-11-23Springboot应用的生产发布入门教程
- 2024-11-23Python编程入门指南
- 2024-11-23Java创业入门:从零开始的编程之旅
- 2024-11-23Java创业入门:新手必读的Java编程与创业指南
- 2024-11-23Java对接阿里云智能语音服务入门详解