洗牌算法

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>洗牌算法</title>
</head>

<body>
    <script>
        /**
 * 洗牌算法
 */
        function shuffle_pick_1(m) {//洗牌 抽牌法
            //生成m张牌
            var arr = new Array(m);
            for (var i = 0; i < m; i++) {
                arr[i] = i;
            }
            //var arr = Array(m).fill().map((_,i)=>i); 优雅的做法
            //每次抽出一张牌,放在另一堆。因为要在数组里抽出元素,
            //把后面的所有元素向前拉一位,所以很耗时
            var arr2 = new Array()
            for (var i = m; i > 0; i--) {
                var rnd = Math.floor(Math.random() * i);
                arr2.push(arr[rnd]);
                arr.splice(rnd, 1);
            }
            return arr2;
        }

        function shuffle_pick(m) {//洗牌 //抽牌法优化牌
            var arr = new Array(m);
            for (var i = 0; i < m; i++) {
                arr[i] = i;
            }
            var arr2 = new Array();
            for (var i = m; i > 0;) {
                var rnd = Math.floor(Math.random() * i);
                arr2.push(arr[rnd]);
                arr[rnd] = arr[--i]
            }
            return arr2;
        }

        function shuffle_swap(m) {//洗牌 换牌法
            var arr = new Array(m);
            for (var i = 0; i < m; i++) {
                arr[i] = i;
            }
            //第i张与任意一张牌换位子,换完一轮即可
            for (var i = 0; i < m; i++) {
                var rnd = Math.floor(Math.random() * (i + 1)),
                    tmp = arr[rnd];
                arr[rnd] = arr[i];
                arr[i] = tmp;
            }
            return arr;
        }

        function shuffle_insert_1(m) {//洗牌 插牌法
            var arr = [0];
            ////每次生成一张最大的牌,插在随机的某张牌前。因为要在数组里插入元素,把后面的所有元素向后挤一位,所以很耗时。
            for (var i = 1; i < m; i++) {
                arr.splice(Math.floor(Math.random() * (i + 1)), 0, i);
            }
            return arr;
        }

        function shuffle_insert(m) {//洗牌 //插牌法优化版,可以用数学归纳法证明,这种洗牌是均匀的。
            var arr = new Array(m);
            arr[0] = 0;
            for (var i = 1; i < m; i++) {
                var rnd = Math.floor(Math.random() * (i + 1));
                arr[i] = arr[rnd];
                arr[rnd] = i;
            }
            return arr;
        }

        function withLog(fn, name) {
            return function (args) {
                var start = new Date();
                var result = fn(args);
                var end = new Date();
                console.log(name + ' 耗时:', end - start);
                return result;
            }
        }
        var fns = [shuffle_pick_1, shuffle_pick, shuffle_swap, shuffle_insert_1, shuffle_insert];
        var fnNames = ['抽牌法', '抽牌法优化', '换牌法', '插牌法', '插牌法优化'];
        for (var i = 0; i < fns.length; i++) {
            var ret = withLog(fns[i], fnNames[i])(10000);
        }
    </script>
</body>

</html>

 

posted @ 2017-08-07 16:46  sivkun  阅读(341)  评论(0编辑  收藏  举报