當前位置:首頁 » 操作系統 » 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中的高效插入方法。

熱點內容
查看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 瀏覽:947
竹壓縮板材 發布:2024-10-26 12:21:32 瀏覽:754