晴明的博客园 GitHub      CodePen      CodeWars     

[js] 几种排序算法以及性能比较

冒泡排序

比较相邻的元素。如果第一个比第二个大,就交换他们两个。
对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。在这一点,最后的元素应该会是最大的数。
针对所有的元素重复以上的步骤,除了最后一个。
持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。

            var testArray = [],
                start = 0,
                end = 0,
                consume = 0;
            for (var i = 0; i < 20000; ++i) {
                testArray[i] = Math.floor((Math.random() * 1000) + 1);
            }
            //console.info(testArray);
            function bubbleSort(arr) {
                //console.warn(arr);
                var numElements = arr.length,
                    temp;
                for (var outer = numElements; outer > 1; --outer) {
                    for (var inner = 0; inner < outer; ++inner) {
                        if (arr[inner] > arr[inner + 1]) {
                            temp = arr[inner];
                            arr[inner] = arr[inner + 1];
                            arr[inner + 1] = temp;
                        }
                        //console.log(arr);
                    }
                    //console.error(arr);
                }
                //console.info(arr);
                return arr;
            }
            start = Date.now();
            bubbleSort(testArray);
            end = Date.now();
            consume = end - start;
            //console.log(testArray); //会改变原数组
            console.log('bubbleSort:' + consume);
            //20000数量数组消耗时间为:2125-2145 ms

 

 //稍微优雅一点的写法

   function bubble(a) {
        let arr = a;
        let l = arr.length;
        while (l) {
            for (let j = 0; j < l; j++) {
                let left = arr[j];
                let right = arr[j + 1];
                if (left > right) {
                    arr[j] = right;
                    arr[j + 1] = left;
                }
            }
            l--;
        }
        return arr;
    }
    console.error(bubble([8, 7, 6, 5, 4, 3, 2, 1]));

 

选择排序

每一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,直到全部待排序的数据元素排完。

            var testArray = [],
                start = 0,
                end = 0,
                consume = 0;
            for (var i = 0; i < 20000; ++i) {
                testArray[i] = Math.floor((Math.random() * 1000) + 1);
            }
            //            for (var i = 0; i < 5; ++i) {
            //                testArray[i] = Math.floor((Math.random() * 100) + 1);
            //            }
            //console.info(testArray);
            function selectionSort(arr) {
                //console.warn(arr);
                var min, temp;
                for (var outer = 0; outer < arr.length - 1; ++outer) {
                    min = outer;
                    for (var inner = outer + 1; inner < arr.length; ++inner) {
                        if (arr[inner] < arr[min]) {
                            min = inner;
                        }
                    }
                    temp = arr[outer];
                    arr[outer] = arr[min];
                    arr[min] = temp;
                    //console.log(arr);
                }
                //console.info(arr);
                return arr;
            }
            start = Date.now();
            selectionSort(testArray);
            end = Date.now();
            consume = end - start;
            //console.log(testArray); //会改变原数组
            console.log('selectionSort:' + consume);
            //20000数量数组消耗时间为:420-430 ms

 

插入排序

每步将一个待排序的纪录,按其关键码值的大小插入前面已经排序的文件中适当位置上,直到全部插入完为止。

            var testArray = [],
                start = 0,
                end = 0,
                consume = 0;
                        for (var i = 0; i < 20000; ++i) {
                            testArray[i] = Math.floor((Math.random() * 1000) + 1);
                        }
//            for (var i = 0; i < 5; ++i) {
//                testArray[i] = Math.floor((Math.random() * 100) + 1);
//            }
            //console.info(testArray);
            function insertionSort(arr) {
                //console.warn(arr);
                var temp, inner;
                for (var outer = 1; outer <= arr.length - 1; ++outer) {
                    temp = arr[outer];
                    inner = outer;
                    while (inner > 0 && (arr[inner - 1] >= temp)) {
                        arr[inner] = arr[inner - 1];
                        --inner;
                    }
                    arr[inner] = temp;
                    //console.log(arr);
                }
                //console.info(arr);
                return arr;
            }
            start = Date.now();
            insertionSort(testArray);
            end = Date.now();
            consume = end - start;
            //console.log(testArray); //会改变原数组
            console.log('insertionSort:' + consume);
            //20000数量数组消耗时间为:180-195 ms

 

希尔排序

是直接插入排序算法的一种更高效的改进版本。

动画演示

#自定义间隔

            var testArray = [],
                start = 0,
                end = 0,
                consume = 0;
            //                        for (var i = 0; i < 20000; ++i) {
            //                            testArray[i] = Math.floor((Math.random() * 1000) + 1);
            //                        }
            for (var i = 0; i < 5; ++i) {
                testArray[i] = Math.floor((Math.random() * 100) + 1);
            }
            //console.info(testArray);
            function shellsort(arr) {
                //console.warn(arr);
                var gaps = [5, 3, 1];
                for (var g = 0; g < gaps.length; ++g) {
                    for (var i = gaps[g]; i < testArray.length; ++i) {
                        var temp = testArray[i];
                        for (var j = i; j >= gaps[g] &&
                            testArray[j - gaps[g]] > temp; j -= gaps[g]) {
                            testArray[j] = testArray[j - gaps[g]];
                            //console.info(arr);
                        }
                        testArray[j] = temp;
                        //console.log(arr);
                    }
                    //console.error(arr);
                }
                //console.warn(arr);
                return arr;
            }            
            start = Date.now();
            shellsort(testArray);
            end = Date.now();
            consume = end - start;
            //console.log(testArray); //会改变原数组
            console.log('shellsort:' + consume);

#动态间隔

            var testArray = [],
                start = 0,
                end = 0,
                consume = 0;
            for (var i = 0; i < 20000; ++i) {
                testArray[i] = Math.floor((Math.random() * 1000) + 1);
            }
            //            for (var i = 0; i < 5; ++i) {
            //                testArray[i] = Math.floor((Math.random() * 100) + 1);
            //            }
            //console.info(testArray);
            function shellsort(arr) {
                //console.warn(arr);
                var N = arr.length,
                    h = 1,
                    temp;
                while (h < N / 3) {
                    h = 3 * h + 1;
                }
                while (h >= 1) {
                    for (var i = h; i < N; i++) {
                        for (var j = i; j >= h && arr[j] < arr[j - h]; j -= h) {
                            temp = arr[j];
                            arr[j] = arr[j - h];
                            arr[j - h] = temp;
                        }
                    }
                    h = (h - 1) / 3;
                }
                //console.log(arr);
                return arr;
            }
            start = Date.now();
            shellsort(testArray);
            end = Date.now();
            consume = end - start;
            //console.log(testArray); //会改变原数组
            console.log('shellsort:' + consume);
            //20000数量数组消耗时间为:10ms左右

 归并排序

将两个顺序序列合并成一个顺序序列的方法。

#自底向上的归并排序

            var testArray = [],
                start = 0,
                end = 0,
                consume = 0;
            for (var i = 0; i < 20000; ++i) {
                testArray[i] = Math.floor((Math.random() * 1000) + 1);
            }
            //            for (var i = 0; i < 5; ++i) {
            //                testArray[i] = Math.floor((Math.random() * 100) + 1);
            //            }
            //console.info(testArray);
            function mergeSort(arr) {
                //console.warn(arr);
                if (arr.length < 2) {
                    return;
                }
                var step = 1;
                var left, right;
                while (step < arr.length) {
                    left = 0;
                    right = step;
                    while (right + step <= arr.length) {
                        mergeArrays(arr, left, left + step, right, right + step);
                        left = right + step;
                        right = left + step;
                    }
                    if (right < arr.length) {
                        mergeArrays(arr, left, left + step, right, arr.length);
                    }
                    step *= 2;
                }
                //console.log(arr);
                return arr;
            }

            function mergeArrays(arr, startLeft, stopLeft, startRight, stopRight) {
                var rightArr = new Array(stopRight - startRight + 1);
                var leftArr = new Array(stopLeft - startLeft + 1);
                k = startRight;
                for (var i = 0; i < (rightArr.length - 1); ++i) {
                    rightArr[i] = arr[k];
                    ++k;
                }
                k = startLeft;
                for (var i = 0; i < (leftArr.length - 1); ++i) {
                    leftArr[i] = arr[k];
                    ++k;
                }
                rightArr[rightArr.length - 1] = Infinity; // a sentinel value
                leftArr[leftArr.length - 1] = Infinity; // a sentinel value
                var m = 0;
                var n = 0;
                for (var k = startLeft; k < stopRight; ++k) {
                    if (leftArr[m] <= rightArr[n]) {
                        arr[k] = leftArr[m];
                        m++;
                    } else {
                        arr[k] = rightArr[n];
                        n++;
                    }
                }
                //console.info("left array - ", leftArr);
                //console.info("right array - ", rightArr);
            }
            start = Date.now();
            mergeSort(testArray);
            end = Date.now();
            consume = end - start;
            //console.log(testArray); //会改变原数组
            console.log('mergeSort:' + consume);
            //20000数量数组消耗时间为:10-20ms

 

快速排序

首先任意选取一个数据(通常选用数组的第一个数)作为关键数据,然后将所有比它小的数都放到它前面,所有比它大的数都放到它后面,这个过程称为一趟快速排序。

            var testArray = [],
                start = 0,
                end = 0,
                consume = 0;
                        for (var i = 0; i < 20000; ++i) {
                            testArray[i] = Math.floor((Math.random() * 1000) + 1);
                        }
//            for (var i = 0; i < 5; ++i) {
//                testArray[i] = Math.floor((Math.random() * 100) + 1);
//            }
            //console.info(testArray);
            function quickSort(arr) {
                //console.warn(arr);
                if (arr.length == 0) {
                    return [];
                }
                var left = [];
                var right = [];
                var pivot = arr[0];
                for (var i = 1; i < arr.length; i++) {
                    //console.info('基准值:' + pivot + '  当前元素' + arr[i]);
                    if (arr[i] < pivot) {
                        //console.error('移动:' + arr[i] + '  到左边');
                        left.push(arr[i]);
                    } else {
                        //console.error('移动:' + arr[i] + '  到右边');
                        right.push(arr[i]);
                    }
                }
                return quickSort(left).concat(pivot, quickSort(right));
            }
            start = Date.now();
            quickSort(testArray);
            //console.log(quickSort(testArray));
            end = Date.now();
            consume = end - start;
            //console.log(testArray); //会改变原数组
            console.log('quickSort:' + consume);
            //20000数量数组消耗时间为:50-60ms

 

sort()排序

            var testArray = [],
                start = 0,
                end = 0,
                consume = 0;
            for (var i = 0; i < 20000; ++i) {
                testArray[i] = Math.floor((Math.random() * 1000) + 1);
            }
            start = Date.now();
            testArray.sort();
            //console.log(quickSort(testArray));
            end = Date.now();
            consume = end - start;
            //console.log(testArray); //会改变原数组
            console.log('Sort:' + consume);
            //20000数量数组消耗时间为:20-30ms

 

posted @ 2016-03-16 15:50  晴明桑  阅读(1910)  评论(0编辑  收藏  举报