js数值排序中冒泡算法的4种简单实现
实现数组排序的算法很多,其中冒泡算法是比较简单的
冒泡的基本原理是相邻的两个数进行比较,按照排序的条件进行互换,例如对数值从小到大排序,
随着不断的互换,最大的那个值会慢慢冒泡到数组的末端
基于这个原理我们就可以写冒泡排序了
为了简单起见下面的例子都是对数值数组进行从小到大排序,先模拟一个20个字符的数组
function getRandomArr(n) { let arr = []; for (let i = 0; i < n; i++) { arr.push(~~(Math.random() * 100)); } return arr } let randomArr = getRandomArr(20);
第一种冒泡算法
从原理可知,冒泡算法最少是需要2层循环的,当其中一个数值冒泡到末端时,这个数值下次就不需要参与循环了,这样循环的范围就会慢慢缩小,最后数组完成排序
function bubbleSort(arr) { let len = arr.length; let temp; let i = len - 1; while(i > 0) { for (let j = 0; j < i; j++) { if (arr[j] > arr[j + 1]) { temp = arr[j]; arr[j] = arr[j + 1]; arr[j + 1] = temp; } } i--;//不断缩小范围 } return arr; } console.log(randomArr)//[ 93, 72, 29, 17, 82, 26, 56, 71, 35, 48, 37, 42, 3, 11, 33, 66, 81, 53, 59, 53 ] console.log('bubbleSort', bubbleSort(randomArr.concat()));//bubbleSort [ 3, 11, 17, 26, 29, 33, 35, 37, 42, 48, 53, 53, 56, 59, 66, 71, 72, 81, 82, 93 ]
在冒泡的过程中,我们可以发现,如果数组后面部分已经排好序了,也就是不用再交换双方的位置时,只要记录好最后一次交换的位置,就有很大的可能缩小下次循环的范围,这样就能提高冒泡的性能(这只是猜想)
第二种冒泡算法
function bubbleSort2(arr) { let len = arr.length; let i = len - 1; let temp; let pos;//用来记录位置的 while (i > 0) { pos = 0;//初始为0如果数组一开始已经排好序了,那么就可以很快终止冒泡 for (let j = 0; j < i; j++) { if (arr[j] > arr[j + 1]) { pos = j; temp = arr[j]; arr[j] = arr[j + 1]; arr[j + 1] = temp; } } i = pos; } return arr; } console.log(randomArr)//[47, 31, 85, 65, 44, 56, 54, 5, 67, 44, 76, 13, 90, 12, 83, 72, 2, 69, 58, 60] console.log('bubbleSort2', bubbleSort2(randomArr.concat()));//bubbleSort2 [2, 5, 12, 13, 31, 44, 44, 47, 54, 56, 58, 60, 65, 67, 69, 72, 76, 83, 85, 90]
其实对于第一种循环,是从左到右进行冒泡,我们也可以从右到左冒泡,但是从右到左的方法和第一种基本就一样了,但是我们可以在内层循环中实现先向左冒泡,再向右冒泡
第三种冒泡方法
function bubbleSort3(arr) { let len = arr.length; let low = 0; let higth = len - 1; let temp; while (low < higth) { for (let j = low; j < higth; j++) { if (arr[j] > arr[j + 1]) { temp = arr[j]; arr[j] = arr[j + 1]; arr[j + 1] = temp; } } higth--; for (let j = higth; j > low; j--) { if (arr[j] < arr[j - 1]) { temp = arr[j]; arr[j] = arr[j - 1]; arr[j - 1] = temp; } } low++; } return arr; } console.log(randomArr)//[40, 78, 16, 97, 38, 27, 66, 44, 45, 31, 12, 1, 99, 68, 36, 42, 40, 54, 6, 42] console.log('bubbleSort3', bubbleSort3(randomArr.concat()));//bubbleSort3 [1, 6, 12, 16, 27, 31, 36, 38, 40, 40, 42, 42, 44, 45, 54, 66, 68, 78, 97, 99]
最后可以结合第三种和第二种方法
第四种冒泡的方法
function bubbleSort4(arr) { let len = arr.length; let low = 0; let higth = len - 1; let temp; while (low < higth) { let hPos = 0; let lPos = higth; for (let j = low; j < higth; j++) { if (arr[j] > arr[j + 1]) { hpos = j; temp = arr[j]; arr[j] = arr[j + 1]; arr[j + 1] = temp; } } heigth = hPos; for (let j = higth; j > low; j--) { if (arr[j] < arr[j - 1]) { lPos = j; temp = arr[j]; arr[j] = arr[j - 1]; arr[j - 1] = temp; } } low = lPos; } return arr; } console.log(randomArr)//[40, 78, 16, 97, 38, 27, 66, 44, 45, 31, 12, 1, 99, 68, 36, 42, 40, 54, 6, 42] console.log('bubbleSort4', bubbleSort4(randomArr.concat()));//[1, 6, 12, 16, 27, 31, 36, 38, 40, 40, 42, 42, 44, 45, 54, 66, 68, 78, 97, 99]
下面对这4种方法在chrome控制台下进行一个简单的性能测试
var randomArr = getRandomArr(10000); console.time('1'); bubbleSort(randomArr.concat()); console.timeEnd('1'); console.time('2'); bubbleSort2(randomArr.concat()); console.timeEnd('2'); console.time('3'); bubbleSort3(randomArr.concat()); console.timeEnd('3'); console.time('4'); bubbleSort4(randomArr.concat()); console.timeEnd('4'); VM371:4 1: 329.705ms VM371:7 2: 379.501ms VM371:10 3: 310.843ms VM371:13 4: 306.847ms
在经过多次测试发现一个有趣的现象执行最快的是第4种方法,最慢的是第2种,没错最慢的是我认为可以提高性能的第2种方法,这就相当尴尬了,不知道有哪位小伙伴可以解释一下
相关推荐
wonner 2020-06-03
清溪算法 2019-12-24
justaipanda 2010-05-10
ZhuZhuWonder 2019-07-01
tuonioooo 2016-10-20
dushine00 2019-06-28
YUAN 2019-04-29
humothetrader 2018-01-15
danwenxuan 2014-08-31
CallmeZhe 2010-05-22
tulensa 2006-11-20
xiekch 2019-02-21