JS--排序之快排和归并

时光总嘲笑我的痴心妄想 提交于 2020-03-21 22:24:46

JS排序算法之快排和归并

快速排序

原理: 选择一个key(一般是第一个元素), 将数组划分为两个区域. 左边全部区域小于等于key, 右边全部大于key. 然后在通过这种方法将每个区域划分为两个区域. 整个过程可以递归实现,以此实现整个数据有序

  • 时间复杂度: O(n*log(n))
  • 最坏时间复杂度: O(n^2)
    • 最坏情况: 原数组是升序(降序), 需要排成降序(升序)
  • 不稳定的排序
  • 特性: 数组分块,且左边区域小于右边(升序)
  • 不稳定原因: 元素交换是跨元素直接交换, 相邻相同元素可能发生位置交换
  • 性能: 最好的的快速排序方法

示例过程:

function quickSort(ary) {
    let n = ary.length;
        function sort(ary, start, end) {
            if(end <= start) return;
            let i = start,
                j = end,
                key = ary[start]; // 设置第一个元素为key
            while(true) {
                // 从左向右找到大于key的元素位置(大于key循环停止, i就是该元素位置)
                while(ary[++i] < key) {
                    // 到达末尾退出循环
                    if(i === end) break;
                }
                // 从右向左找到小于key的元素位置
                while(ary[--j] > key) {
                    // 到达头部退出循环
                    if(j === start) break;
                }
                // 如果 i和j相交, 直接退出循环
                if(i>=j) break;
                // 交换左右两边元素
                let temp = ary[i];
                ary[i] = ary[j];
                ary[j] = temp;
            }
            // 交换key和最后一个小于key值的元素(就是arr[j])
            let temp = ary[start];
            ary[start] = ary[j];
            ary[j] = temp;
            sort(ary, start, j);
            sort(ary, j+1, end);
        }
    sort(ary, 0, n);
    return ary;
}

效果演示:

归并排序

原理: 先将数组不断折分为左右两个小数组, 然后再对小数组排序并合并起来

  • 时间复杂度: O(n*log(n))
  • 稳定的排序算法
    • 稳定原因: 排序是两两元素值之间的互换, 相邻相同元素位置不会被改变
  • 性能: 速度仅次与快排(如果使用递归方法,在处理庞大数据时可能出现内存不足情况), 比快排稳定,任何时候时间复杂度都是O(n*long(n));
  • 特点: 数组会不断对半平分, 然后再排序合并. 先小区间有序,再大区间, 区间间隔相等.
  • 优化: TimeSort排序

示例过程:
示例过程图

    function mergeSort(items) {
        if (items.length == 1) {
            return items;
        }
        //将数组对半平分为左右两个数组
        var middle = Math.floor(items.length / 2),
            left = items.slice(0, middle),
            right = items.slice(middle);

        function merge(left, right) {
            var result = [];
            // 通过这个循环来排序
            while (left.length > 0 && right.length > 0) {
                if (left[0] < right[0]) {
                    /*shift()方法用于把数组的第一个元素从其中删除,并返回第一个元素的值。*/
                    result.push(left.shift());
                } else {
                    result.push(right.shift());
                }
            }
            //合并两个数组
            return result.concat(left).concat(right);
        }

    // 递归调用
    return merge(mergeSort(left), mergeSort(right));
}

效果示例

gif来源: 排序算法-散点可视化

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!