当前位置:首页 » 操作系统 » vba算法

vba算法

发布时间: 2024-10-26 11:33:44

㈠ VBA洗牌法原理谁能文字阐释一下

我找了此资料,一起共享


下面直接介绍【经典数组洗牌法】的算法原理:

假如你有一个布袋或者抽屉,里面有m=10个不同号码的球,

你要随机抽取,并保证不重复……

那么正确的做法是:

1.每次从布袋中随机抽取一个球;注意到rnd()函数的正确抽取目数应该是=m

2.抽取出来的这一个球要另外放置开;

【如果不另外放置,而只是记下号码后再把球返回布袋,接下来就无法保证这个已经被抽到过的球又被重复抽到。】

而这个,就是1楼代码中没有考虑到而产生的重大bug

3.继续从布袋中随机抽取另一个球;

注意到此时布袋中剩余球的数量少了一个是m-1了,因此rnd()函数的正确抽取目数应该是=m-1

4.抽取出来的这第2个球和已经抽取出来的第1个球放置在一齐,并且按新的序列排放。

5.重复以上随机抽取过程,注意到关键是:

a.每次抽取的母数即剩余球数要递减1个

b.每次抽取出来的新球要分开放置,不能放回布袋!

c.新抽取出来的球,要和前面已经取出的球按新的序列整齐排放。

d.剩下最最重要一点,但是看到这里好多人都可能不会意识到的一个问题:

布袋中剩余球如何放置?

即,假定布袋中球也是像放置在抽屉中那样,有序地排放着的,

那么每次抽走一个球,必然留下一个空格……【这就很麻烦了!】

因为大家知道,实际上数组中用rnd()函数只能是返回一个一定区间内的值及数组位置,

而如果留有空位的话,随机性就无法保证高效……万一抽到空格怎么办?难道重新再抽一次?

如果抽到只剩最后一个求时,则原先的布袋/抽屉中,将留下9个空格,则每次随机函数的计算结果,将有90%的概率仍旧抽到空格……

这就完蛋了。


【经典数组洗牌法】的真正原理是:

1.从m个值中【随机确定一个位置r】(利用Rnd()随机函数计算,具体算法是【以剩余数m为母数】区间进行随机值计算并取整返回位置)

2.把这个位置即要被抽取的元素(球)先取出拿在手中【存入临时变量t】,【腾出一个空位】。

3.把数组的【第1位置】(Lbound)元素拿出来,【放入刚才腾出的r空位】。并随即【腾出】了数组第一位置作为【新的空位】

(也可以以数组的最末位置(UBound)作为开始位置进行处理,具体算法代码就不太一样了)

4.把上述第2步骤取出的、存入了临时变量t的元素(球),准确地放入【新的空位】,即数组第一位置。

这个数组第一位置中的【新元素】,就是已经被有效抽取的第1个不重复值。

然后,继续

1.抽第2个数时,以剩余母数m-1作为随机计算区间而返回一个随机值并计算取整返回第2个不重复的随机位置r

2.把这个位置r即要被抽取的第2个元素(球)先取出拿在手中【存入临时变量t】,【腾出一个空位】。

3.把数组的【第2位置】元素拿出来,【放入刚才腾出的r空位】。并随即【腾出】了数组第2位置作为【新的空位】

(也可以以数组的最末倒数第2位置进行处理,具体算法代码就不太一样了)

4.把上述第2步骤取出的、存入了临时变量t的元素(球),准确地放入【新的空位】,即数组第2位置。

这个数组第2位置中的【新元素】,就是已经被有效抽取的第2个不重复值。

以上述方式反复进行,抽取、置换,存放,直到最后一个,也不会产生重复抽取了。


下面是【经典数组洗牌法】实际代码中最简单的代码例子:

对于一个下标1开始的一维数组,从中随机抽取n个元素返回。

SubGetRnd(arr,n)
Randomize
Fori=1Ton'正序洗牌1ton简化代码
r=Int(Rnd()*(n-i+1))+i
t=arr(r):arr(r)=arr(i):arr(i)=t'下标1开始一维代码
Next
EndSub

'正序洗牌1ton简化代码详解:

SubGetRnd(arr,n)

Randomize'随机种子初始化,保证每次代码运行或打开文件时出现的随机序列是和上次文件保存/运行时不同的序列。

Fori=1Ton'遍历1ton

r=Int(Rnd()*(n-i+1))+i、

'按每次剩余母数(n-i+1)作为随机计算区间,计算Rnd()*(n-i+1)然后用int()函数去整,得到剩余数中的随机位置。

'紧接着,这个随机位置后面【+i】处理,转化成从新的起点i开始的随机位置r。即不再包括已经抽取出的结果,避免重复。

t=arr(r)'把这个随机位置r中的元素取出,存入临时变量t

arr(r)=arr(i)'把【第i个】位置中的元素【放入刚才腾出的r空位】(实际数据操作时并没有腾出,而只是用新的值直接覆盖掉。)

arr(i)=t'把上面刚刚【腾出的i空位】放入刚才存放在临时变量t中的当前最新抽取元素,完成一次抽取过程。

Next'循环抽取、置换、存贮抽取结果

EndSub

㈡ VBA高手解析这一段递归组合算法看不懂

Subzuhe(x%,z%,sr$,ggAsByte)'x新加的数字序号,z原有的数字总和,sr算式,gg原有个数
Ifz+arr(x,1)=hAndgg=g-1Then'和与个数都符合
k=k+1
arr1(k,1)=sr&arr(x,1)&"="&h
ExitSub
EndIf
Ifx<UBound(arr)Andz<hThen'没到最后一个数且和还不足
Ifz+arr(x,1)<hThen'和不足'本行疑似有误,改为Ifgg<g-1Then应省时
zuhex+1,z+arr(x,1),sr&arr(x,1)&"+",gg+1'增加一个数
EndIf
zuhex+1,z,sr,gg'取下一个数
EndIf
EndSub

㈢ Excel VBA 插入多行的4种方法 & 算法对比

本文提供了通过Excel VBA插入多行的四种方法,并对每种方法的算法效率进行了对比。以插入500行为例,来分析不同方法的性能和效率。

方法1(普通):最直观但也是最慢的方法,即一行一行地插入。插入500行大约需要27.34375秒,效率低下。算法复杂度为O(n),即与行数线性相关。

方法2(算法):这种方法利用算法加快插入速度,相较于方法1快得多,大约需要0.5390625秒。算法复杂度为O(logN+1),其中N为行数,故插入500行的复杂度约为9。尽管速度提升显着,但并非最优。

方法3(最快):使用了VBA中的Range.Resize()方法,实现插入行操作只需一行代码,速度非常快,只需0.078125秒。从算法角度看,复杂度为O(1),即与行数无关。但应注意,插入行数增加时,操作时间会相应增加。

方法4(便利):利用Range().EntireRow.Insert和Rows().Insert方法实现插入行,代码简洁,速度同样为0.078125秒。复杂度也为O(1),与行数无关。此外,此方法还允许指定插入行的起始位置,增加了便利性。

总结,文中介绍的方法虽然简单,但通过这些代码,可以清晰地理解算法的效率和Big O表示法的概念。面向初学者,希望本文能帮助大家理解和掌握VBA中的高效插入方法。

热点内容
标准配置什么意思 发布:2024-10-26 14:35:27 浏览:880
查看linux所有用户 发布:2024-10-26 14:11:15 浏览:15
useraddftp 发布:2024-10-26 13:59:21 浏览:621
安卓免费私密相册哪个好用 发布:2024-10-26 13:41:20 浏览:639
湛江移动服务器ip 发布:2024-10-26 13:12:17 浏览:634
找回dns服务器地址 发布:2024-10-26 12:48:23 浏览:240
王者皮肤系统脚本 发布:2024-10-26 12:46:44 浏览:508
电脑配置8g怎么查看 发布:2024-10-26 12:40:58 浏览:811
布朗编程 发布:2024-10-26 12:35:27 浏览:307
php平滑重启 发布:2024-10-26 12:25:33 浏览:948