目的:ES6标准下的JS算法的一些实现代码。(作为记录和启发)
内容:排序、搜索和随机算法。冒泡排序,选择排序,插入排序,归并排序,快速排序,计数排序,桶排序,基数排序;顺序搜索,二分搜索,内插搜索;Fisher-Yates随机。
一、基础算法
1、排序
1.1、冒泡排序
概念:冒泡排序比较所有相邻的两个项,如果第一个比第二个大,则交换他们。元素项向上移动至正确的顺序,就好像气泡升至表面一样。其复杂度是O(n2)。
1 const Compare = {
2 LESS_THAN: -1,
3 BIGGER_THAN: 1,
4 EQUALS: 0
5 };
6
7 function defaultCompare(a, b) {
8 if (a === b) {
9 return Compare.EQUALS;
10 }
11 return a < b ? Compare.LESS_THAN : Compare.BIGGER_THAN;
12 }
13
14 function swap(array, a, b) {
15 /* const temp = array[a];
16 array[a] = array[b];
17 array[b] = temp; */
18 [array[a], array[b]] = [array[b], array[a]];
19 }
20
21 function bubbleSort(array, compareFn = defaultCompare) {
22 const {length} = array;
23 for (let i = 0; i < length; i++){
24 for (let j = 0; j < length - 1; j++) {
25 if (compareFn(array[j], array[j + 1]) === Compare.BIGGER_THAN) {
26 swap(array, j, j + 1);
27 }
28 }
29 }
30 return array;
31 }
32
33 function createNonSortedArray(size){
34 var array = [];
35 for (let i = size; i > 0; i--){
36 array.push(i);
37 }
38 return array;
39 }
40
41 const array = createNonSortedArray(5);
42 console.log(array);
43 console.log(bubbleSort(array))
bubbleSort
1.2、改进的冒泡排序
说明:如果从内循环减去外循环中已跑过的轮数,就可以避免内循环中所有不必要的比较。其复杂度是O(n2)。(嵌套了两个循环)
1 const Compare = {
2 LESS_THAN: -1,
3 BIGGER_THAN: 1,
4 EQUALS: 0
5 };
6
7 function defaultCompare(a, b) {
8 if (a === b) {
9 return Compare.EQUALS;
10 }
11 return a < b ? Compare.LESS_THAN : Compare.BIGGER_THAN;
12 }
13
14 function swap(array, a, b) {
15 /* const temp = array[a];
16 array[a] = array[b];
17 array[b] = temp; */
18 [array[a], array[b]] = [array[b], array[a]];
19 }
20
21 function modifiedBubbleSort(array, compareFn = defaultCompare) {
22 const {length} = array;
23 for (let i = 0; i < length; i++){
24 for (let j = 0; j < length - 1 - i; j++) {
25 if (compareFn(array[j], array[j + 1]) === Compare.BIGGER_THAN) {
26 swap(array, j, j + 1);
27 }
28 }
29 }
30 return array;
31 }
32
33 function createNonSortedArray(size){
34 var array = [];
35 for (let i = size; i > 0; i--){
36 array.push(i);
37 }
38 return array;
39 }
40
41 const array = createNonSortedArray(5);
42 console.log(array);
43 console.log(modifiedBubbleSort(array))
modifiedBubbleSort
1.3、选择排序
概念:选择排序算法是一种原址比较排序算法。选择排序大致的思路是找到数据结构中的最小值并将其放置在第一位,接着找到第二小的值并将其放置在第二位,以此类推。其复杂度是O(n2)。(嵌套了两个循环)
1 const Compare = {
2 LESS_THAN: -1,
3 BIGGER_THAN: 1,
4 EQUALS: 0
5 };
6
7 function defaultCompare(a, b) {
8 if (a === b) {
9 return Compare.EQUALS;
10 }
11 return a < b ? Compare.LESS_THAN : Compare.BIGGER_THAN;
12 }
13
14 function swap(array, a, b) {
15 /* const temp = array[a];
16 array[a] = array[b];
17 array[b] = temp; */
18 [array[a], array[b]] = [array[b], array[a]];
19 }
20
21 function selectionSort(array, compareFn = defaultCompare) {
22 const {length} = array;
23 let indexMin;
24 for (let i = 0; i < length -1; i++) {
25 indexMin = i;
26 for (let j = i; j < length; j++) {
27 if (compareFn(array[indexMin], array[j]) === Compare.BIGGER_THAN) {
28 indexMin = j;
29 }
30 }
31 if (i !== indexMin) {
32 swap(array, i, indexMin);
33 }
34 }
35 return array;
36 }
37
38
39 function createNonSortedArray(size){
40 var array = [];
41 for (let i = size; i > 0; i--){
42 array.push(i);
43 }
44 return array;
45 }
46
47 const array = createNonSortedArray(5);
48 console.log(array);
49 console.log(selectionSort(array))
selectionSort
1.4、插入排序
概念:插入排序每次排一个数组项,以此方式构建最后的排序数组。假定第一项已经排序了。接着,它和第二项进行比较--第二项是应该待在原位还是插入到第一项之前呢?这样,头两项就已正确排序,接着和第三项比较(它是该插入到第一、第二还是第三的位置呢),以此类推。(排序小型数组时,插入排序比选择排序和冒泡排序性能要好)
1 const Compare = {
2 LESS_THAN: -1,
3 BIGGER_THAN: 1,
4 EQUALS: 0
5 };
6
7 function defaultCompare(a, b) {
8 if (a === b) {
9 return Compare.EQUALS;
10 }
11 return a < b ? Compare.LESS_THAN : Compare.BIGGER_THAN;
12 }
13
14 function swap(array, a, b) {
15 /* const temp = array[a];
16 array[a] = array[b];
17 array[b] = temp; */
18 [array[a], array[b]] = [array[b], array[a]];
19 }
20
21 function insertionSort(array, compareFn = defaultCompare) {
22 const {length} = array;
23 let temp;
24 for (let i = 1; i < length; i++) {
25 let j = i;
26 temp = array[j];
27 while(j > 0 && compareFn(array[j - 1], temp) === Compare.BIGGER_THAN) {
28 array[j] = array [j - 1];
29 j--;
30 }
31 array[j] = temp;
32 }
33 return array;
34 }
35
36
37
38
39 const array = [3, 5, 1, 4, 2];
40 console.log(array);
41 console.log(insertionSort(array));
insertionSort
1.5 归并排序
概念:归并排序是一种分而治之算法,其思想是将原始数组切分较小的数组,直到每个小数组只有一个位置,接着讲小数组归并成较大的数组,直到最后只有一个排序完毕的大数组。归并排序是第一个可以实际使用的排序算法,归并排序性能不错(比上三种排序好),其复杂度为O(nlog(n))。
1 const Compare = {
2 LESS_THAN: -1,
3 BIGGER_THAN: 1,
4 EQUALS: 0
5 };
6
7 function defaultCompare(a, b) {
8 if (a === b) {
9 return Compare.EQUALS;
10 }
11 return a < b ? Compare.LESS_THAN : Compare.BIGGER_THAN;
12 }
13
14 function swap(array, a, b) {
15 /* const temp = array[a];
16 array[a] = array[b];
17 array[b] = temp; */
18 [array[a], array[b]] = [array[b], array[a]];
19 }
20
21 function merge(left, right, compareFn) {
22 let i = 0;
23 let j = 0;
24 const result = [];
25 while (i < left.length && j < right.length) {
26 result.push(compareFn(left[i], right[j]) === Compare.LESS_THAN ? left[i++] : right[j++]);
27
28 }
29 return result.concat(i < left.length ? left.slice(i) : right.slice(j));
30 }
31
32 function mergeSort(array, compareFn = defaultCompare) {
33 if (array.length > 1) {
34 const {length} = array;
35 const middle = Math.floor(length / 2);
36 const left = mergeSort(array.slice(0, middle), compareFn);
37 const right = mergeSort(array.slice(middle, length), compareFn);
38 array = merge(left, right, compareFn);
39 }
40 return array;
41 }
42
43
44
45
46
47 const array = [8,7,6,5,4,3,2,1];
48 console.log(array);
49 console.log(mergeSort(array));
mergeSort
1.6 快速排序
概念:快速排序也许是最常用的排序算法了,它的复杂度为O(nlog(n)),且性能通常比其他复杂度为O(nlog(n))的排序算法好。快速排序也是使用分而治之的思想,将原始数组分为较小的数组(但它没有像归并排序那样将它们分割开)。思路:选择主元(pivot);划分(partition)操作;对划分后的小数组重复前两步操作,直至数组已完全排序。
1 const Compare = {
2 LESS_THAN: -1,
3 BIGGER_THAN: 1,
4 EQUALS: 0
5 };
6
7 function defaultCompare(a, b) {
8 if (a === b) {
9 return Compare.EQUALS;
10 }
11 return a < b ? Compare.LESS_THAN : Compare.BIGGER_THAN;
12 }
13
14 function swap(array, a, b) {
15 /* const temp = array[a];
16 array[a] = array[b];
17 array[b] = temp; */
18 [array[a], array[b]] = [array[b], array[a]];
19 }
20
21 function partition(array, left, right, compareFn){
22 const pivot = array[Math.floor((left + right) / 2)];
23 let i = left;
24 let j = right;
25 while (i <= j) {
26 while (compareFn(array[i], pivot) === Compare.LESS_THAN) {
27 i++;
28 }
29 while (compareFn(array[j],pivot) === Compare.BIGGER_THAN) {
30 j--;
31 }
32 if (i <= j) {
33 swap(array, i ,j);
34 i++;
35 j--;
36 }
37 }
38 return i;
39 }
40
41 function quick(array, left, right, compareFn) {
42 let index;
43 if (array.length > 1) {
44 index = partition(array, left, right, compareFn);
45 if (left < index - 1) {
46 quick(array, left, index - 1, compareFn);
47 }
48 if (index < right) {
49 quick(array, index, right, compareFn);
50 }
51 }
52 return array;
53 }
54
55 function quickSort(array, compareFn = defaultCompare) {
56 return quick(array, 0, array.length - 1, compareFn);
57 }
58
59
60 const array = [8,7,6,5,4,3,2,1];
61 console.log(array);
62 console.log(quickSort(array));
quickSort
1.7 计数排序
概念:计数排序是一个分布式排序,使用已经组织好的辅助数据结构(称为桶),然后进行合并,得到排好序的数组。计数排序使用一个用来存储每个元素在原始数组中出现次数的临时数组。在所有元素都计数完成后,临时数组已拍好序并可迭代以构建排序后的结果数组。它是一个优秀的整数排序算法,时间复杂度为O(n+k),其中k是临时计数数组的大小;但是它确实需要更多的内存来存放临时数组。
1 const Compare = {
2 LESS_THAN: -1,
3 BIGGER_THAN: 1,
4 EQUALS: 0
5 };
6
7 function defaultCompare(a, b) {
8 if (a === b) {
9 return Compare.EQUALS;
10 }
11 return a < b ? Compare.LESS_THAN : Compare.BIGGER_THAN;
12 }
13
14 function swap(array, a, b) {
15 /* const temp = array[a];
16 array[a] = array[b];
17 array[b] = temp; */
18 [array[a], array[b]] = [array[b], array[a]];
19 }
20 function findMaxValue(array) {
21 let max = array[0];
22 for (let i = 1; i < array.length - 1; i++) {
23 if (array[i] > max) {
24 max = array[i];
25 }
26 }
27 return max;
28 }
29 function countingSort(array) {
30 if (array.length < 2) {
31 return array;
32 }
33 const maxValue = findMaxValue(array);
34 let sortedIndex = 0;
35 const counts = new Array(maxValue + 1);
36 array.forEach(element => {
37 if (!counts[element]) {
38 counts[element] = 0;
39 }
40 counts[element]++;
41 });
42 counts.forEach((element, i) => {
43 while(element > 0) {
44 array[sortedIndex++] = i;
45 element--;
46 }
47 });
48 return array;
49 }
50
51
52
53 const array = [5,4,3,2,3,1];
54 console.log(array);
55 console.log(countingSort(array));
countingSort
1.8 桶排序
概念:桶排序(箱排序)也是分布式排序算法,它将元素分为不同的桶(较小的数组),再使用一个简单的排序算法,例如插入排序,来对每个桶进行排序。然后,它将所有的桶合并为结果数组。
1 const Compare = {
2 LESS_THAN: -1,
3 BIGGER_THAN: 1,
4 EQUALS: 0
5 };
6
7 function defaultCompare(a, b) {
8 if (a === b) {
9 return Compare.EQUALS;
10 }
11 return a < b ? Compare.LESS_THAN : Compare.BIGGER_THAN;
12 }
13
14 function swap(array, a, b) {
15 /* const temp = array[a];
16 array[a] = array[b];
17 array[b] = temp; */
18 [array[a], array[b]] = [array[b], array[a]];
19 }
20 const insertionSort = (array, compareFn = defaultCompare) => {
21 const { length } = array;
22 let temp;
23 for (let i = 1; i < length; i++) {
24 let j = i;
25 temp = array[i];
26 // console.log('to be inserted ' + temp);
27 while (j > 0 && compareFn(array[j - 1], temp) === Compare.BIGGER_THAN) {
28 // console.log('shift ' + array[j - 1]);
29 array[j] = array[j - 1];
30 j--;
31 }
32 // console.log('insert ' + temp);
33 array[j] = temp;
34 }
35 return array;
36 };
37
38 function creatBuckets(array, bucketSize) {
39 let minValue = array[0];
40 let maxValue = array[0];
41 for (let i = 1; i < array.length; i++) {
42 if (array[i] < minValue) {
43 minValue = array[i];
44 } else if (array[i] > maxValue) {
45 maxValue = array[i];
46 }
47 }
48 const bucketCount = Math.floor((maxValue - minValue) / bucketSize) + 1;
49 const buckets = [];
50 for (let i = 0; i < bucketCount; i++) {
51 buckets[i] = [];
52 }
53 for (let i = 0; i < array.length; i++) {
54 buckets[Math.floor((array[i] - minValue) / bucketSize)].push(array[i]);
55 }
56 return buckets;
57 }
58 function sortBuckets(buckets) {
59 const sortedArray = [];
60 for (let i = 0; i < buckets.length; i++) {
61 if (buckets[i] != null) {
62 insertionSort(buckets[i]);
63 sortedArray.push(...buckets[i]);
64 }
65 }
66 return sortedArray;
67 }
68
69 function bucketSort (array, bucketSize = 5) {
70 if (array.length < 2) {
71 return array;
72 }
73 const buckets = creatBuckets(array, bucketSize);
74 return sortBuckets(buckets);
75 }
76
77
78
79 const array = [5,4,3,2,6,1,7,10,9,8];
80 console.log(array);
81 console.log(bucketSort(array));
bucketSort
1.9 基数排序
概念:基数排序是一个分布式排序算法,它根据数字的有效位或者基数将整数分布到桶中。基数是基于数组中值的记数制的。
1 const Compare = {
2 LESS_THAN: -1,
3 BIGGER_THAN: 1,
4 EQUALS: 0
5 };
6
7 function defaultCompare(a, b) {
8 if (a === b) {
9 return Compare.EQUALS;
10 }
11 return a < b ? Compare.LESS_THAN : Compare.BIGGER_THAN;
12 }
13
14 function swap(array, a, b) {
15 /* const temp = array[a];
16 array[a] = array[b];
17 array[b] = temp; */
18 [array[a], array[b]] = [array[b], array[a]];
19 }
20 function findMaxValue(array, compareFn = defaultCompare) {
21 if (array && array.length > 0) {
22 let max = array[0];
23 for (let i = 1; i < array.length; i++) {
24 if (compareFn(max, array[i]) === Compare.LESS_THAN) {
25 max = array[i];
26 }
27 }
28 return max;
29 }
30 return undefined;
31 }
32 function findMinValue(array, compareFn = defaultCompare) {
33 if (array && array.length > 0) {
34 let min = array[0];
35 for (let i = 1; i < array.length; i++) {
36 if (compareFn(min, array[i]) === Compare.BIGGER_THAN) {
37 min = array[i];
38 }
39 }
40 return min;
41 }
42 return undefined;
43 }
44
45 const getBucketIndex = (value, minValue, significantDigit, radixBase) =>
46 Math.floor(((value - minValue) / significantDigit) % radixBase);
47
48 const countingSortForRadix = (array, radixBase, significantDigit, minValue) => {
49 let bucketsIndex;
50 const buckets = [];
51 const aux = [];
52 for (let i = 0; i < radixBase; i++) {
53 buckets[i] = 0;
54 }
55 for (let i = 0; i < array.length; i++) {
56 bucketsIndex = getBucketIndex(array[i], minValue, significantDigit, radixBase);
57 buckets[bucketsIndex]++;
58 }
59 for (let i = 1; i < radixBase; i++) {
60 buckets[i] += buckets[i - 1];
61 }
62 for (let i = array.length - 1; i >= 0; i--) {
63 bucketsIndex = getBucketIndex(array[i], minValue, significantDigit, radixBase);
64 aux[--buckets[bucketsIndex]] = array[i];
65 }
66 for (let i = 0; i < array.length; i++) {
67 array[i] = aux[i];
68 }
69 return array;
70 };
71 function radixSort(array, radixBase = 10) {
72 if (array.length < 2) {
73 return array;
74 }
75 const minValue = findMinValue(array);
76 const maxValue = findMaxValue(array);
77 let significantDigit = 1;
78 while ((maxValue - minValue) / significantDigit >= 1) { // console.log('radix sort for digit ' + significantDigit);
79 array = countingSortForRadix(array, radixBase, significantDigit, minValue);
80 significantDigit *= radixBase;
81 }
82 return array;
83 }
84 const array = [456,789,123,1,32,4,243,321,42,90,10,999];
85 console.log(array);
86 console.log(radixSort(array));
radixSort
2、搜索算法
2.1 顺序搜索
概念:顺序或线性搜索是最基本的搜索算法。它的机制是将每一个数据结构中的元素和我们要找的元素作比较。(最低效)
1 const DOES_NOT_EXIST = -1;
2 function defaultEquals(a, b) {
3 return a === b;
4 }
5
6 function sequentialSearch(array, value, equalsFn = defaultEquals) {
7 for (let i = 0; i < array.length; i++) {
8 if (equalsFn(array[i], value)) {
9 return i;
10 }
11 }
12 return DOES_NOT_EXIST;
13 }
14
15 const array = [456,789,123,1,32,4,243,321,42,90,10,999];
16 console.log(array);
17 console.log(sequentialSearch(array,999));
18 console.log(sequentialSearch(array,1000));
sequentialSearch
2.2 二分搜索
二分搜索要求被搜索的数组已排序。步骤:1、选择数组中间值;2、如果选中值是待搜索值,那么算法执行完毕;如果带搜索值比选中值要小,则返回步骤1并在选中值左边的子数组中寻找(较小);4、 如果带搜索值比选中值要大,则返回步骤1并在选中值右边的子数组中寻找(较大)。
1 const Compare = {
2 LESS_THAN: -1,
3 BIGGER_THAN: 1,
4 EQUALS: 0
5 };
6 const DOES_NOT_EXIST = -1;
7 function defaultCompare(a, b) {
8 if (a === b) {
9 return Compare.EQUALS;
10 }
11 return a < b ? Compare.LESS_THAN : Compare.BIGGER_THAN;
12 }
13
14 function swap(array, a, b) {
15 /* const temp = array[a];
16 array[a] = array[b];
17 array[b] = temp; */
18 [array[a], array[b]] = [array[b], array[a]];
19 }
20
21 function partition(array, left, right, compareFn) {
22 const pivot = array[Math.floor((right + left) / 2)];
23 let i = left;
24 let j = right;
25
26 while (i <= j) {
27 while (compareFn(array[i], pivot) === Compare.LESS_THAN) {
28 i++;
29 }
30 while (compareFn(array[j], pivot) === Compare.BIGGER_THAN) {
31 j--;
32 }
33 if (i <= j) {
34 swap(array, i, j);
35 i++;
36 j--;
37 }
38 }
39 return i;
40 }
41 function quick(array, left, right, compareFn) {
42 let index;
43 if (array.length > 1) {
44 index = partition(array, left, right, compareFn);
45 if (left < index - 1) {
46 quick(array, left, index - 1, compareFn);
47 }
48 if (index < right) {
49 quick(array, index, right, compareFn);
50 }
51 }
52 return array;
53 }
54 function quickSort(array, compareFn = defaultCompare) {
55 return quick(array, 0, array.length - 1, compareFn);
56 }
57
58 function binarySearch(array, value, compareFn = defaultCompare) {
59 const sortedArray = quickSort(array);
60 let low = 0;
61 let high = sortedArray.length;
62 while(low <= high) {
63 const mid = Math.floor((low + high) / 2);
64 const element = sortedArray[mid];
65 if (compareFn(element, value) === Compare.LESS_THAN) {
66 low = mid + 1;
67 } else if (compareFn(element, value) === Compare.BIGGER_THAN) {
68 high = mid - 1;
69 } else {
70 return mid;
71 }
72 }
73 return DOES_NOT_EXIST;
74 }
75
76
77 const array = [456,789,123,1,32,4,243,321,42,90,10,999];
78 console.log(array);
79 console.log(quickSort(array));
80 console.log(binarySearch(array,42))
81 console.log(binarySearch(array,43));
binarySearch
2.3 内插搜索
概念:内插搜索是改良版的二分搜索。步骤:1、使用position公式选中一个值;2、如果选中值是待搜索值,那么算法执行完毕;如果带搜索值比选中值要小,则返回步骤1并在选中值左边的子数组中寻找(较小);4、 如果带搜索值比选中值要大,则返回步骤1并在选中值右边的子数组中寻找(较大)。
1 const Compare = {
2 LESS_THAN: -1,
3 BIGGER_THAN: 1,
4 EQUALS: 0
5 };
6 const DOES_NOT_EXIST = -1;
7 function lesserEquals(a, b, compareFn) {
8 const comp = compareFn(a, b);
9 return comp === Compare.LESS_THAN || comp === Compare.EQUALS;
10 }
11 function defaultCompare(a, b) {
12 if (a === b) {
13 return Compare.EQUALS;
14 }
15 return a < b ? Compare.LESS_THAN : Compare.BIGGER_THAN;
16 }
17 function biggerEquals(a, b, compareFn) {
18 const comp = compareFn(a, b);
19 return comp === Compare.BIGGER_THAN || comp === Compare.EQUALS;
20 }
21 function defaultDiff(a, b) {
22 return Number(a) - Number(b);
23 }
24 function defaultEquals(a, b) {
25 return a === b;
26 }
27 function swap(array, a, b) {
28 /* const temp = array[a];
29 array[a] = array[b];
30 array[b] = temp; */
31 [array[a], array[b]] = [array[b], array[a]];
32 }
33
34 function partition(array, left, right, compareFn) {
35 const pivot = array[Math.floor((right + left) / 2)];
36 let i = left;
37 let j = right;
38
39 while (i <= j) {
40 while (compareFn(array[i], pivot) === Compare.LESS_THAN) {
41 i++;
42 }
43 while (compareFn(array[j], pivot) === Compare.BIGGER_THAN) {
44 j--;
45 }
46 if (i <= j) {
47 swap(array, i, j);
48 i++;
49 j--;
50 }
51 }
52 return i;
53 }
54 function quick(array, left, right, compareFn) {
55 let index;
56 if (array.length > 1) {
57 index = partition(array, left, right, compareFn);
58 if (left < index - 1) {
59 quick(array, left, index - 1, compareFn);
60 }
61 if (index < right) {
62 quick(array, index, right, compareFn);
63 }
64 }
65 return array;
66 }
67 function quickSort(array, compareFn = defaultCompare) {
68 return quick(array, 0, array.length - 1, compareFn);
69 }
70 function interpolationSearch(
71 array,
72 value,
73 compareFn = defaultCompare,
74 equalsFn = defaultEquals,
75 diffFn = defaultDiff
76 ) {
77 quickSort(array);
78 const {length} = array;
79 let low = 0;
80 let high = length - 1;
81 let position = -1;
82 let delta = -1;
83 while (
84 low <= high
85 && biggerEquals(value, array[low], compareFn)
86 && lesserEquals(value, array[high],compareFn)
87 ) {
88 delta = diffFn(value, array[low]) / diffFn(array[high], array[low]);
89 position = low + Math.floor((high - low) * delta);
90 if (equalsFn(array[position], value)) {
91 return position;
92 }
93 if (compareFn(array[position], value) === Compare.LESS_THAN) {
94 low = position + 1;
95 } else {
96 high = position - 1;
97 }
98 }
99 return DOES_NOT_EXIST;
100 }
101
102
103 const array = [456,789,123,1,32,4,243,321,42,90,10,999];
104 console.log(array);
105 console.log(quickSort(array));
106 console.log(interpolationSearch(array,42))
107 console.log(interpolationSearch(array,43));
interpolationSearch
3、随机算法
3.1、Fisher-Yates随机算法
概念:迭代数组,从最后一位开始并将当前位置和一个随机位置进行交换。这个随机位置比当前位置小。这样,这个算法可以保证随机过得位置不会再被随机一次(洗扑克牌的次数越多,随机效果越差)。
1 function swap(array, a, b) {
2 /* const temp = array[a];
3 array[a] = array[b];
4 array[b] = temp; */
5 [array[a], array[b]] = [array[b], array[a]];
6 }
7
8 function shuffle(array) {
9 for (let i = array.length -1; i > 0; i--) {
10 const randomIndex = Math.floor((Math.random() * (i+1)));
11 swap(array, i, randomIndex);
12 }
13 return array;
14 }
15
16 const array = [1,2,3,4,5,6,7,8,9];
17 console.log(array);
18 console.log(shuffle(array));
shuffle