洗牌算法(Shuffle Algorithm)Fisher-Yates C语言版

目录

文章目录

前言

一、什么是Fisher-Yates?

二、洗牌算法的运用

为什么是倒序遍历?

总结


前言

这是我的第一篇csdn博客,以此来记录一个大一计算机学生,从大一到大三秋招的编程学习历程,并督促自己,希望能一点点进步,不要磨灭了那份心气,fighting!

2025.9.25


笔者目前打算在国庆假期结束前学习完C语言基础,由于笔者是从零开始的计算机学习之路,不像诸多大佬一样在中学时就有算法基础,所以笔者开始写的东西可能比较简单qwq,只是每次学习后的一次正反馈hhh。


一、什么是Fisher-Yates?

简单来说,是将一组元素随机打乱(将两个不同的元素交换),类似于洗牌的效果,所以又叫洗牌算法。这种方法能保证洗牌的随机性和均匀性。
Fisher-Yates 算法的核心思想是: 每次从未处理的元素中随机选择一个,然后与未处理部分的最后一个元素交换,且从数组的末尾开始倒序遍历。
  1. 随机性:由于采用了随机数生成器和随机种子,即C语言中的rand( )函数和srand(time(NULL))种子,保证了这种方法的随机性.

  2. 均匀性,即每个元素在每个位置出现的概率是相等的,可以从数学概率的角度来解释(贝叶斯公式)

    我们以一个长度为 n 的数组为例,证明每个元素出现在任意位置的概率都是 1/n:

    1.
       对于最后一个位置 :
       
       - 第一次迭代时,我们从整个数组中随机选择一个元素放到最后位置
       - 任何特定元素被选中的概率是 1/n
     2.
       对于倒数第二个位置 :
       
       - 我们从未处理的前 n-1 个元素中随机选择一个
       - 一个特定元素出现在这里的概率 = (该元素未被选中到最后位置的概率) × (该元素被选中到倒数第二位置的概率)
       - 计算:(n-1)/n × 1/(n-1) = 1/n

二、洗牌算法的运用

下面以C语言中打乱数组中的数据这个简单的问题为例子。

#include <stdio.h>
#include <time.h>
#include <stdlib.h>
int main()
{
	int arr[5] = {1,2,3,4,5};
	int len = sizeof(arr) / sizeof(int);
	srand(time(NULL));
    for (int i = len-1; i >=0; i--)
	{
		
		int num = rand() % (i+1);
		int temp = arr[i];
		arr[i] = arr[num];
		arr[num] = temp;
        
	}
	printf("打乱后的数组/n");
	for (int i = 0; i < len; i++)
	{
		printf("%d\n", arr[i]);

	}
	return 0;
	

以temp作为中间量进行交换,可以保证数据不重复。注意最后打印打乱后的数组要在循环外,不然会出现重复。

为什么是倒序遍历?

避免重复选择,提高算法效率。实际上"正序Fisher-Yates变体"也是可行的。


总结

Fisher-Yates 洗牌算法是一种经典的洗牌算法,能够在 O(n) 时间内将数组随机打乱,并确保所有排列的生成是等概率的。它广泛应用于随机排序、游戏设计和数据抽样等领域,是随机算法中的一个基础算法。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值