STL系列十一 随机三趣题——随机重排,文件中随机取一行,生成N个随机数。

STL系列十一 随机三趣题——随机重排,文件中随机取一行,生成N个随机数 阅读详情

本文将介绍三个有趣的随机问题,分别是随机重新排列、从文件中随机取一行数据、生成N个随机数。

 

一.随机重新排列

将一个序列打乱并对其进行随机的重新排列,关键在于每种序列的被选择概率要一样,不然有失“公平”。现在让我们来寻找如何保证每种序列被选择的概率一样大的算法。

首先假设这个数组只有二个元素,设数组a为{1, 2},显然这个数组只有二种可能的排列,要么是{1,2}要么是{2,1}。很容易想到一种方法——只要第二个元素有50%的概率与第一个元素交换即可。用代码表现下:

if (rand() % 2 == 0)

       swap(a[0], a[1])

由于rand() % 2的结果要么为0,要么为1,且各占50%的概率。因此swap(a[0], a[1])的执行概率也是50%,如果执行了,结果会是{2,1}。没有执行,结果会是{1,2}。所以这样两种排列出现的可能均为50%。

 

接下来再假充这个数组有三个元素设数组a为{1, 2,3},这个数组有六种可能的排列,要么是{1,2,3}、{1,3,2}、{2,1,3}、{2,3,1}、{3,1,2}和{3,2,1}。这么多的排列看起来好象有点复杂,不知道从何下手。其实结合上面的分析,我们可以这样考虑:

1.先调整前二个元素即{1, 2,3}先生成{1,2,3}或{2,1,3}。

2.然后对{1,2,3},第三个元素以1/3的概率与第一,第二,第三个元素进行交换就可以等概率的得到{3,2,1}、{1,3,2}和{1,2,3}。

3.同理对{2,1,3},可以等概率的得到{3,1,2}、{2,3,1}和{2,1,3}。

根据贝叶斯公式,不难计算出由这些排列出现的可能性都是1/2 * 1/3 = 1/6。完全符合每种序列的被选择概率相同的要求。

 

这样随机重新排列的算法就找到了,下面给出示意代码:

//随机重新排列
//参照STL中的random_shuffle
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
inline void Swap(int *a, int *b)
{
	int c = *a;
	*a = *b;
	*b = c;
}
//随机重新排列函数
void Random_shuffle(int a[], int n)
{
	srand(time(NULL));
	for (int i = 1; i < n; i++)
		Swap(&a[i], &a[rand() % (i + 1)]);
}
void PrintfIntArray(int a[], int n)
{
	for (int i = 0; i < n; i++)
		printf("%d ", a[i]);
	putchar('\n');
}
int main()
{
	printf("           随机重新排列 \n");
	printf("--- by MoreWindows( http://blog.youkuaiyun.com/MoreWindows )  ---\n\n");

	const int MAXN = 8;
	int a[MAXN] = {1, 2, 3, 4, 5, 6, 7, 8};

	printf("原数组:\n");
	PrintfIntArray(a, MAXN);

	Random_shuffle(a, MAXN);

	printf("随机重新排列后:\n");
	PrintfIntArray(a, MAXN);
	return 0;
}

运行结果如下:

有兴趣的童鞋可以用STL中的random_shuffle()来改写上面的程序,相信知道其实现原理后会对random_shuffle()有更深的认识。

另外,这种按顺序先后来交换元素得到新排列的方法与生成全排列非常类似,可以参考《STL系列之十 全排列(百度迅雷笔试题)》然后对比下两种方法在思路上相似之处。

 

二.从文件中随机取一行数据

如果先统计文件有多少行,再根据rand() % 行数选择对应行也是可以行的,但效率显然会有点低了。有没有一种方法可以只遍历文件一次了?请看代码:

//从文件中取机选取一行
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main()
{
	printf("           从文件中取机选取一行 \n");
	printf("--- by MoreWindows( http://blog.youkuaiyun.com/MoreWindows )  ---\n\n");

	int i, num, nChooseNum;
	const char strFileName[] = "in.txt";
	
	freopen(strFileName, "r", stdin);
	srand(time(NULL));
	i = 1;
	while (scanf("%d", &num) != EOF)
	{
		if (rand() % i == 0)
			nChooseNum = num;
		i++;
	}
	printf("从文件中选取出: %d\n", nChooseNum);
	return 0;
}

运行结果如下(in.txt中为0到9,每个数字占一行):

对代码进行下讲解,以三行数据为例,首先对文本的第一行,rand() % 1,结果必然为0。所以第一行已被选中了,然后对第二行,rand()%2,结果要么为0,要么为1。故第二行有 50的可能性被选中,然后对第三行,rand()%3,显然被选中的概率为1/3。故有:

选中第一行的概率为1 * 1/2 * 2/3 = 1/3。

选中第二行的概率为1/2 * 2/3 = 1/3。

选中第三行的概率为1/3。

故每一行被选中是等概率的。

 

三.生成N个随机数

这个有很多方法,常见方法用set记录已经生成的数据,然后判断set的大小是否符合要求。代码如下所示:

//生成n个指定范围的随机数
#include <stdio.h>
#include <time.h>
#include <set>
//生成n个[s, e)范围的数
void GetRandNumberInRange(int *a, int n, int s, int e)
{
	int   i, j;
	std::set<int>  m;
	std::set<int>::iterator setpos;
	
	srand(time(NULL));	
	while (m.size() < n)
	{
		j = rand() % (e - s) + s;
		m.insert(j);
	}
	
	i = 0;
	for (setpos = m.begin(); setpos != m.end(); setpos++)
		a[i++] = *setpos;
}
void PrintfIntArray(int a[], int n)
{
	for (int i = 0; i < n; i++)
		printf("%d ", a[i]);
	putchar('\n');
}
int main()
{
	const int NMAX = 20;
	const int NUMSTART = 1;
	const int NUMEND = 100;

	printf("           生成%d个%d到%d之间的数 \n", NMAX, NUMSTART, NUMEND);
	printf("--- by MoreWindows( http://blog.youkuaiyun.com/MoreWindows )  ---\n\n");	

	int    a[NMAX];
	
	GetRandNumberInRange(a, NMAX, NUMSTART, NUMEND + 1);
	PrintfIntArray(a, NMAX);
	return 0;
}

运行结果如下:

这种方法会导致调用随机函数次数过多,从而效率低下。可以采用一种改进的方法,如要生成3个1到10之间的数,取10-3=7,因此可以先t=rand()%7,保存t,然后再t=rand()%8,如果t这个数已经存在就取8保存,再t=rand()%9,同样如果t这个数已经存在就取9保存。这样只会调用3次随机函数。当然这种方法不能完全保证每个数字被选择概率相同,算是牺牲“公平”来保证效率吧。

生成N个随机数的改进方法代码如下:

//生成n个指定范围的随机数
#include <set>
#include <cstdio>
#include <cstdlib>
#include <ctime>
//在[s, e)区间上随机取n个数并存放到a[]中
void GetRandomNum(int *a, int n, int s, int e)
{
	std::set<int> set_a;
	srand(time(NULL));
	for (int i = e - n; i < e; i++)
	{
		int num = (rand() % (i - s)) + s;
		if (set_a.find(num) == set_a.end())
			set_a.insert(num);
		else
			set_a.insert(i);
	}
	i = 0;
	std::set<int>::iterator pos;
	for (pos = set_a.begin(); pos != set_a.end(); pos++)
		a[i++] = *pos;
}
void PrintfIntArray(int a[], int n)
{
	for (int i = 0; i < n; i++)
		printf("%d ", a[i]);
	putchar('\n');
}
int main()
{
	const int NMAX = 20;
	const int NUMSTART = 1;
	const int NUMEND = 100;
	
	printf("           生成%d个%d到%d之间的数 改进版\n", NMAX, NUMSTART, NUMEND);
	printf("--- by MoreWindows( http://blog.youkuaiyun.com/MoreWindows )  ---\n\n"); 
	int a[NMAX];
	
	GetRandomNum(a, NMAX, NUMSTART, NUMEND + 1);
	PrintfIntArray(a, NMAX);
	return 0;
}

运行结果如下:

 

有关随机的趣味题就介绍到这里,有任何问题欢迎和我交流,直接留言或发送邮件均可。邮箱:morewindows@126.com

 

下一篇《STL系列十二链表排序的6次改进(对《STL源码剖析》作个补充)》将会对STL中的链表排序进行详细讲解,如果看过《STL源码剖析》书中142页的链表排序代码将会更有收获。更多内容,请继续关注MoreWindows

 

转载请标明出处,原文地址:http://blog.youkuaiyun.com/morewindows/article/details/7659532





 

SAP SD信贷管理实战:从配置到风险控制的完整指南(附后台路径) 本文详细解析了SAP SD信贷管理的完整配置流程与风险控制策略,涵盖信贷控制范围设置、风险分级机制及动态控制配置。通过实战案例和后台路径指引,帮助企业实现从客户信用评估到实时监控的全流程管理,有效降低坏账风险并优化资金安全。 阅读详情

相关推荐

小白的MatSWMM使用心路(二)——用matlab修改INP文件参数/使用matlab查找txt内容并修改多行内容

说是修改inp,但是里面的内容大部分还是讲怎么修改txt的……(?)。包含如何找到需要的参数(关键字)位置,以及修改那个位置的txt这样的内容。希望能帮助大家吧……Matlab你要多出好用的功能啊!

weixin_44276743的博客 4530

全排列和组合(STL和C语言递归解法)

从n个不同元素中任取m(m≤n)个元素,按照一定的顺序排列起来,叫做从n个不同元素中取出m个元素的一个排列。当m=n时所有的排列情况叫全排列。

lclchong的博客 1437

【机器学习(一)】从零到一:用sklearn构建你的第一个机器学习项目

本文为机器学习新手提供了一个完整的端到端实战指南。通过使用Python的scikit-learn库,以经典的鸢尾花数据集为例,详细演示了从环境搭建、数据探索、预处理、模型训练与评估,到超参数调优和模型保存的全流程。文章旨在帮助读者快速构建第一个机器学习项目,掌握核心工作流和工程实践。

weixin_29070861的博客 467

用STL函数permutation实现全排列

用STL函数permutation实现全排列

qq_74221023的博客 356

Zynq 双核AMP 通信

4、配置离线编译(这里不讲),配置linux的内核地址空间(0x4000_0000改为0x2000_0000),以及单核启动。CPU1设置为0x2000_0000~0x3FFF_FFFF(也可以小于0x3FFF_FFFF)如果禁用CPU1的L2 cache,在CPU1的bsp里面添加编译时候所需要的宏。3、配置工程,将vivado产生的.xsa文件复制到amp_com项目目录下。9、使用petalinux-package --boot 打包。一、vivado工程。5、编译u-boot。

y183128184的博客 1086

9.23华为OD机试真题 新系统 - 小菊的寻宝之旅 (Java/Py/C/C++/Js/Go)

9.23华为OD机试真题 新系统 - 小菊的寻宝之旅 (Java/Py/C/C++/Js/Go)

算法大师! 979

C++模板库STL之全排列

C++模板库STL之全排列

Serven的博客 1万+

【WebRTC】【Unity】Unity Web RTC1-Unity中简单实现远程画面

平台:基本常用平台包括安卓,苹果(max和IOS),Windows64,Linux都行。10. 注意,如果从移动设备浏览器连接服务,信令服务器的SSL证书一定要先设好。想要在Unity中实现实时远程桌面,找到了Render Streaming这个手段,本篇介绍相应的使用方法和实例。8. 打开电脑浏览器,地址栏输入http://127.0.0.1,点击Receiver Sample。新建Unity项目,模板选Third Person,Project Name随意。启动App,控制台出现如下信息表示成功。

每日出拳老爷子的博客 2518

STL:全排列算法

字典法非递归全排列 这里解析的是《STL源码剖析》中全排列的算法,属于非递归算法; 下面我用尽可能简单的语言让读者明白什么是字典法全排列,额外插一句: 我也很讨厌看全是字的解析,但是我保证这篇解析已经很白话了,稍稍耐心看完,保证能懂 思路: 这里我们以字符串”1234”为例,因为它更容易看出大小关系 ①首先,先理解我这句话 “一个序列的所有排列情况(即全...

桔子 1532

uniapp(全端兼容) - 最新详细实现双色球开奖走势图功能组件,uni-app红球走势图/蓝球走势图,解决双色球 “蓝球连线“ 问题,双色球效果及用线连接每个号码详细教程(同样适用于彩票开奖走势图

uni-app,双色球,安卓app,苹果app,微信小程序,移动端,H5网页,手机网站,微信小程序、支付宝小程序,手机app端,nvue,红球走势,蓝球走势,连线,uniapp(vue):js实现双色球开奖走势图带连线,vue2,vue3,uniApp双色球组件插件,uniapp如何实现双色球走势图和连线,彩票走势图,前端 Vue实现彩票走势图,详细示例,走势图,彩票项目,绘制股票走势图,前端 JS实现彩票开奖走势图 连线,Uniapp有没有双色球的页面代码,红球蓝球的走势图如何做,双色球红球和值尾走势图,

✅ 精选推荐文章 3344

人工智能训练师三级·模型生命周期真题40题|训练→评估→调优全链路通关

本文为人工智能训练师三级考试真题解析系列第2篇,聚焦模型生命周期全链路(训练→评估→调优)。内容包含40道精选真题,覆盖数据划分、模型训练、评估指标、超参数调优4个核心阶段。重点考察:1)数据集的合理划分方法(留出法、交叉验证);2)模型训练的基本原理;3)关键评估指标(准确率、召回率、F1等)的应用场景;4)超参数调优技术(网格搜索、随机搜索等)。通过真题解析帮助考生系统掌握模型生命周期的闭环迭代方法论,提升从数据准备到模型优化的全流程实践能力。适合备考人工智能训练师三级认证的考生学习参考。

白话机器学习 88

STL 全排列

1. 排列序数 Description 如果用a b c d这4个字母组成一个串,有4!=24种,如果把它们排个序,每个串都对应一个序号: abcd 0 abdc 1 acbd 2 acdb 3 adbc 4 adcb 5 bacd 6 badc 7 bcad 8 bcda 9 bdac 10 bdca 11 cabd 12 cadb 13 cbad 14 cbda 15 cdab 16 cdba 17 ... 现在有不多...

qing9611的博客 496

STM32 cubeMX配置串口重定向

这篇文章主要讲解什么是串口重定向,为什么要串口串口重定向。使用printf函数和上位机通信是非常的方便的。希望大家都能够掌握。

m0_49476241的博客 4570

STL系列十一 随机三趣题 随机重排 文件中随机取一行 生成N个随机数

STL系列十一 随机三趣题 随机重排 文件中随机取一行 生成N个随机数

weixin_43417960的博客 175

IDEA的使用指南

IDEA基于java的使用手册,可以最快速的上手,在使用中不断的丰富自己的使用技巧.

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

STL系列十一 随机三趣题——随机重排,文件中随机取一行,生成N个随机数。...

本文将介绍三个有趣的随机问题,分别是随机重新排列、从文件中随机取一行数据、生成N个随机数。 一.随机重新排列 将一个序列打乱并对其进行随机的重新排列,关键在于每种序列的被选择概率要一样,不然有失“公平”。现在让我们来寻找如何保证每种序列被选择的概率一样大的算法。 首先假设这个数组只有二个元素,设数组a为{1, 2},显然这个数组只有二种可能的排列,要么是{1,2}要么是{2,1}。很容易想到一种...

huobengluantiao8 116

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

STL系列之 随机数 随机重排 文件中随机取一行,生成N个随即数

http://blog.youkuaiyun.com/morewindows/article/details/7659532   本文将介绍三个有趣的随机问题,分别是随机重新排列、从文件中随机取一行数据、生成N个随机数。 一.随机重新排列 将一个序列打乱并对其进行随机的重新排列,关键在于每种序列的被选择概率要一样,不然有失“公平”。现在让我们来寻找如何保证每种序列被选择的概率一样大的算法。 首先

miao6664659的专栏 1490

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

随机重排,文件中随机取一行,生成N个随机数。

本文将介绍三个有趣的随机问题,分别是随机重新排列、从文件中随机取一行数据、生成N个随机数。  原文地址:http://blog.youkuaiyun.com/morewindows/article/details/7659532 一.随机重新排列 将一个序列打乱并对其进行随机的重新排列,关键在于每种序列的被选择概率要一样,不然有失“公平”。现在让我们来寻找如何保证每种序列被选择的

继续微笑lsj 1523

STL系列--- 随机三趣题——随机重排,文件中随机取一行,生成N个随机数。

本文将介绍三个有趣的随机问题,分别是随机重新排列、从文件中随机取一行数据、生成N个随机数。 一.随机重新排列 将一个序列打乱并对其进行随机的重新排列,关键在于每种序列的被选择概率要一样,不然有失“公平”。现在让我们来寻找如何保证每种序列被选择的概率一样大的算法。 首先假设这个数组只有二个元素,设数组a为{1, 2},显然这个数组只有二种可能的排列,要么是{1,2}要么是{2,1}

402

【白话经典算法系列之十三】随机生成和为S的N个正整数——投影法

【白话经典算法系列之十三】随机生成和为S的N个正整数——投影法      随机生成和为S的N个正整数有很多种解法。下面讲解一种比较高效且比较有趣味性的解法——投影法。    以生成和为20的4个数为例,可以先生成随机生成0到20之间的三个数字再排序,假设得到了4,7,18。然后在X-Y数轴上画出这三个数,如下图:然后将这些数值投影到Y轴上,可得下图:由图很容易看出AB,BC,CD,DE这四段的长度

MoreWindows Blog 1万+

白话经典算法系列之十三 随机生成和为S的N个正整数——投影法

【白话经典算法系列之十三】随机生成和为S的N个正整数——投影法 随机生成和为S的N个正整数有很多种解法。下面讲解一种比较高效且比较有趣味性的解法——投影法。 以生成和为20的4个数为例,可以先生成随机生成0到20之间的三个数字再排序,假设得到了4,7,18。然后在X-Y数轴上画出这三个数,如下图: 然后将这些数值投影到Y轴上,可得下图: 由图很容易看出AB,BC,CD,DE这四段的...

不二的博客 318
上一篇: 如何在C/C++中动态分配二维数组
下一篇: 微软实习生日记 第一篇 初识微软
MoreWindows
MoreWindows 《白话经典算法》、《秒杀多线程》作者 《白话经典算法》、《秒杀多线程》作者 领域专家: 操作系统技术领域 领域专家: 操作系统技术领域
博客等级 码龄15年 2万+粉丝 157原创
评论 19
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值