首頁 web前端 js教程 JS隨機洗牌演算法之數組隨機排序_javascript技巧

JS隨機洗牌演算法之數組隨機排序_javascript技巧

May 16, 2016 pm 03:08 PM

推薦閱讀:JavaScript學習筆記之數組的增、刪、改、查

JavaScript學習筆記之數組求和方法

JavaScript學習筆記之數組隨機排序

洗牌演算法是一個比較圖像的術語,本質上讓一個陣列內的元素隨機排列。舉例來說,我們有一個如下圖所示的數組,數組長度為 9,數組內元素的值順次分別是 1~9:

從上面這個陣列入手,我們要做的就是打亂數組內元素的順序:


程式碼實作

維基百科上的 Fisher–Yates shuffle 詞條對洗牌演算法做了詳細介紹,以下示範的演算法也是基於其中的理論編寫的:

Array.prototype.shuffle = function() {
var input = this;
for (var i = input.length-1; i >=0; i--) {
var randomIndex = Math.floor(Math.random()*(i+1)); 
var itemAtIndex = input[randomIndex]; 
input[randomIndex] = input[i]; 
input[i] = itemAtIndex;
}
return input;
}
var tempArray = [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ]
tempArray.shuffle();
// and the result is...
alert(tempArray); 
登入後複製

在上面的程式碼中,我們建立了一個 shffle() 方法,該方法用於隨機排列數組內的元素。此外,我們將該方法掛載在了 Array 物件的原型下面,所以任何陣列都可以直接呼叫該方法:

var tempArray = [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ]
tempArray.shuffle(); 
登入後複製

工作原理

看完程式碼之後,讓我們看看它對陣列都做了寫什麼。首先,此方法選取數組的最後一個元素:

接下來決定挑選隨機元素的範圍,從陣列的第一個元素到上一個步驟選取的元素都屬於此範圍:

確定範圍後,從中隨機挑選一個數,這裡假設隨機選取的元素為 4:

然後交換最後一個元素和隨機選取的元素的值:

上面的交換完成後,相當於我們完成了陣列最後一個元素的隨機處理。接下來選取數組內倒數第二的元素:

之所以從後往前處理,是因為這樣便於確定隨機選擇的範圍。這次我們假定隨機到的元素為 2:


接著交換倒數第一個元素和 2 號元素的值,完成倒數第二個元素隨機排列的處理。然後是選取倒數第三個元素,重複先前的操作:

剩下的就是一些重複性的工作,不多做介紹了。

分析程式碼

在上一節給各位用圖例示範了洗牌流程,下面我們從程式碼本身看看洗牌流程。先從 shuffle 函數說起:

Array.prototype.shuffle = function() {
var input = this;
for (var i = input.length-1; i >=0; i--) {
var randomIndex = Math.floor(Math.random()*(i+1)); 
var itemAtIndex = input[randomIndex]; 
input[randomIndex] = input[i]; 
input[i] = itemAtIndex;
}
return input;
} 
登入後複製

shuffle 函式掛載在 Array 物件的原型之下,便於陣列直接呼叫該函數。在 shuffle 函數內部,this 引用的就是呼叫該 shuffle 的陣列:

var input = this;
登入後複製

在上面的程式碼中,我用一個新的變數來引用 this,也就是呼叫 shuffle 函數的陣列。下一步,來看看 for 迴圈內都做了什麼:

for (var i = input.length-1; i >=0; i--) {
var randomIndex = Math.floor(Math.random()*(i+1)); 
var itemAtIndex = input[randomIndex]; 
input[randomIndex] = input[i]; 
input[i] = itemAtIndex;
}
登入後複製

此循環用於遍歷所有數組內的所有元素,並進行隨機交換。請注意,遍歷順序是從後往前進行的,也就是說從 input.length-1 位置的元素開始,知道遍歷到陣列中的第一個元素。遍歷過程中的位置由變數 i 指定。

這裡的變數 i 就是上面圖例中被選取的元素:

洗牌演算法

接下來,使用了兩行程式碼在指定範圍內挑選一個隨機元素:

var randomIndex = Math.floor(Math.random()*(i+1)); 
var itemAtIndex = input[randomIndex];
登入後複製

变量 randomIndex 存储了一个随机数,该随机数可以用作数组的索引,进而提取一个随机元素。注意,该随机数的最大值并不是数组的长度,而是变量 i 的值。

确定了随机元素的索引之后,用新的变量保存该元素的值,然后交换选中元素和随机元素的值:

var itemAtIndex = input[randomIndex];
input[randomIndex] = input[i]; 
input[i] = itemAtIndex;
登入後複製

在这三行代码中,第一行使用新的变量保存了随机元素的值;第二行将选中元素 input[i] 的值赋给随机元素 input[randomIndex];第三行就随机元素的值 itemAtIndex 赋给选中元素 input[i]。本质上是一个互换两个元素的值的过程,并不难理解。

至此,循环内的逻辑就介绍完了,剩下的都是重复操作。

随机性测试


上图是使用 Highcharts 制作的随机性测试图表,以可视化的方式校验本文中洗牌算法的随机性。每次刷新页面都会重新计算和生成该图表。

生成上图的数据是这样计算而来的:首先创建一个数组(上图使用的数组为 [0, 1, 2 ... 18, 19, 20]),然后使用本文中的洗牌算法重新排序,排序完成后记录每一个元素的值……以此步骤执行 100000 次,最后对同一索引位置上的数值进行求和。如此执行 10000 次之后,索引之间的总值应该相差不大。

由计算可得:

以上内容是小编给大家介绍的JS随机洗牌算法之给数组随机排序的相关叙述,希望对大家有所帮助!

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

AI Hentai Generator

AI Hentai Generator

免費產生 AI 無盡。

熱門文章

R.E.P.O.能量晶體解釋及其做什麼(黃色晶體)
1 個月前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳圖形設置
1 個月前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.如果您聽不到任何人,如何修復音頻
1 個月前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.聊天命令以及如何使用它們
1 個月前 By 尊渡假赌尊渡假赌尊渡假赌

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

如何創建和發布自己的JavaScript庫? 如何創建和發布自己的JavaScript庫? Mar 18, 2025 pm 03:12 PM

文章討論了創建,發布和維護JavaScript庫,專注於計劃,開發,測試,文檔和促銷策略。

如何在瀏覽器中優化JavaScript代碼以進行性能? 如何在瀏覽器中優化JavaScript代碼以進行性能? Mar 18, 2025 pm 03:14 PM

本文討論了在瀏覽器中優化JavaScript性能的策略,重點是減少執行時間並最大程度地減少對頁面負載速度的影響。

前端熱敏紙小票打印遇到亂碼問題怎麼辦? 前端熱敏紙小票打印遇到亂碼問題怎麼辦? Apr 04, 2025 pm 02:42 PM

前端熱敏紙小票打印的常見問題與解決方案在前端開發中,小票打印是一個常見的需求。然而,很多開發者在實...

如何使用瀏覽器開發人員工具有效調試JavaScript代碼? 如何使用瀏覽器開發人員工具有效調試JavaScript代碼? Mar 18, 2025 pm 03:16 PM

本文討論了使用瀏覽器開發人員工具的有效JavaScript調試,專注於設置斷點,使用控制台和分析性能。

誰得到更多的Python或JavaScript? 誰得到更多的Python或JavaScript? Apr 04, 2025 am 12:09 AM

Python和JavaScript開發者的薪資沒有絕對的高低,具體取決於技能和行業需求。 1.Python在數據科學和機器學習領域可能薪資更高。 2.JavaScript在前端和全棧開發中需求大,薪資也可觀。 3.影響因素包括經驗、地理位置、公司規模和特定技能。

如何使用源地圖調試縮小JavaScript代碼? 如何使用源地圖調試縮小JavaScript代碼? Mar 18, 2025 pm 03:17 PM

本文說明瞭如何使用源地圖通過將其映射回原始代碼來調試JAVASCRIPT。它討論了啟用源地圖,設置斷點以及使用Chrome DevTools和WebPack之類的工具。

如何使用JavaScript將具有相同ID的數組元素合併到一個對像中? 如何使用JavaScript將具有相同ID的數組元素合併到一個對像中? Apr 04, 2025 pm 05:09 PM

如何在JavaScript中將具有相同ID的數組元素合併到一個對像中?在處理數據時,我們常常會遇到需要將具有相同ID�...

console.log輸出結果差異:兩次調用為何不同? console.log輸出結果差異:兩次調用為何不同? Apr 04, 2025 pm 05:12 PM

深入探討console.log輸出差異的根源本文將分析一段代碼中console.log函數輸出結果的差異,並解釋其背後的原因。 �...

See all articles