JavaScript 排序算法

排序算法:

冒泡排序:频繁交换 ,找出其中最大的放到最后一个 一次找到第二大的放大倒数第二个...最后完成

function bubbleSort(arr) {
            for (let i = 0;i < arr.length - 1;i++) {
                for (let j = 0;j < arr.length - 1 - i;j++) {
                    if (arr[j] > arr[j + 1]) {
                        [arr[j], arr[j + 1]] = [arr[j + 1], arr[j]]
                    }

                }
            }
    return arr;
}

选择排序:
从开头选择一个基准值 遍历一趟选出比这个更小的值最后当前位置与找出来的最终值交换。排列顺序是从前到后

function xuanzeSort(arr) {
            for (let i = 0, min, index;i < arr.length;i++) {
                min = arr[i];
                index = i;
                for (let j = i + 1;j < arr.length;j++) {
                    if (min > arr[j]) {
                        min = arr[j];
                        index = j;
                    }
                }
                arr[index] = arr[i]
                arr[i] = min;
            }
            return arr;
        }

插入排序:
跟我们的打牌一样: 从第一个开始 拿到这个值往前比较 找到比它小的值的时候停下来放在这里,简单就是 找到合适的位置然后插入进去

function charuSort(arr) {
            let index, current;
            for (let i = 1;i < arr.length;i++) {
                index = i - 1;
                current = arr[i]
                while (current < arr[index] && index >= 0) {
                    arr[index + 1] = arr[index];
                    index--;
                }
                arr[index + 1] = current;
            }
            return arr;
        }

快速排序
把数据分成两组,选择最中间的一个值 前后分成两个,比中间这个值大的放后面 比这个值小的放在前面。然后递归排列前后数组即可

var quickSort = function (arr) {
            if (arr.length <= 1) { return arr; }
            var pivotIndex = Math.floor(arr.length / 2);
            var pivot = arr.splice(pivotIndex, 1)[0];
            var left = [];
            var right = [];
            for (var i = 0;i < arr.length;i++) {
                if (arr[i] < pivot) {
                    left.push(arr[i]);
                } else {
                    right.push(arr[i]);
                }
            }
            return quickSort(left).concat([pivot], quickSort(right));
        };

希尔排序:是对插入排序的优化。插入排序一次移动一位,而希尔排序是一次移动gap位。
 希尔排序是基于插入排序的以下两点性质而提出改进方法的:
插入排序在对几乎已经排好序的数据操作时,效率高,即可以达到线性排序的效率。
但插入排序一般来说是低效的,因为插入排序每次只能将数据移动一位。
为更加清晰地说明该排序,贴一张其它地方转载而来的图片

图片

这个代码我看了好一段时间,都有点懵 难理解,最后弄个例子程序一步一步走才看懂了。哎 我真笨
其实这个图对我来说有点误导性。
图上看起来是一组一组的排好序的,但是并不是。 而是设置一个值j = gap的时候,就依次排,排到最后一个 ,只是移动的间隔为gap。上图上的分组是同时在进行排序。这样排到后面的时候前面相应间隔的数是已经排好序了的。

//希尔排序
        function shellSort(arr) {
            let len = arr.length;
            // gap 即为增量
            for (let gap = Math.floor(len / 2);gap > 0;gap = Math.floor(gap / 2)) {
                debugger
                for (let i = gap;i < len;i++) {
                    let j = i;
                    let current = arr[i];
                    while (j - gap >= 0 && current < arr[j - gap]) {
                        arr[j] = arr[j - gap];
                        j = j - gap;
                    }
                    arr[j] = current;
                }
            }
            return arr;
        }

        let arr = [8, 5, 6, 1, 7, 3, 2, 4];
        console.log(shellSort(arr));

希尔排序比直接插入排序优点:
直接插入排序的问题:如果在后面来了一个特别小的元素,需要全部移动,那么排序的效率特别低。
希尔排序优点:如果在数组最后加入一个小元素,他会被很快移到最前面。
归并排序
基本思想:先递归的分解数列,再合并数列
(1)将一个数组拆成A、B两个小组,两个小组继续拆,直到每个小组只有一个元素为止。
(2)按照拆分过程逐步合并小组,由于各小组初始只有一个元素,可以看做小组内部是有序的,合并小组可以被看做是合并两个有序数组的过程。
(3)对左右两个小数列重复第二步,直至各区间只有1个数。
代码实现:

        //辅助函数,传入两个数组,按大小顺序插入新数组然后返回。
        function Merger(a, b) {
            var n = a && a.length;
            var m = b && b.length;
            var c = [];
            var i = 0, j = 0;

            while (i < n && j < m) {
                if (a[i] < b[j])
                    c.push(a[i++]);
                else
                    c.push(b[j++]);
            }

            while (i < n)
                c.push(a[i++]);

            while (j < m)
                c.push(b[j++]);

            console.log("将数组", a, '和', b, '合并为', c)
            return c;
        }
      
//划分数组
        function merge_sort(arr) {
            console.log(arr)
            if (arr.length == 1)
                return arr

            var mid = Math.floor(arr.length / 2)
            var left = arr.slice(0, mid)
            var right = arr.slice(mid)

            return Merger(merge_sort(left), merge_sort(right)); //合并左右部分
        }
        let arr = [8, 5, 6, 1, 7, 3, 2, 4];
        console.log(merge_sort(arr));

原文:归并排序

堆排序
大佬链接:堆排序
前面步骤看懂了,后面看代码有点绕

//堆排序
        // 交换两个节点
        function swap(A, i, j) {
            let temp = A[i];
            A[i] = A[j];
            A[j] = temp;
        }

        // 将 i 结点以下的堆整理为大顶堆,注意这一步实现的基础实际上是:
        // 假设 结点 i 以下的子堆已经是一个大顶堆,shiftDown函数实现的
        // 功能是实际上是:找到 结点 i 在包括结点 i 的堆中的正确位置。后面
        // 将写一个 for 循环,从第一个非叶子结点开始,对每一个非叶子结点
        // 都执行 shiftDown操作,所以就满足了结点 i 以下的子堆已经是一大
        //顶堆
        function shiftDown(A, i, length) {
            let temp = A[i]; // 当前父节点
            // j= 0;i--) {
                shiftDown(A, i, A.length);
            }
            
            // 排序,每一次for循环找出一个当前最大值,数组长度减一
            for (let i = Math.floor(A.length - 1);i > 0;i--) {
                swap(A, 0, i); // 根节点与最后一个节点交换
                shiftDown(A, 0, i); // 从根节点开始调整,并且最后一个结点已经为当
                // 前最大值,不需要再参与比较,所以第三个参数
                // 为 i,即比较到最后一个结点前一个即可
            }
            return A;
        }

        let arr = [8, 5, 6, 1, 7, 3, 2, 4];
        console.log(heapSort(arr));

下面循环调用的shiftDown的时候 是从上到下,并把下面的非叶子节点的大小顺序移动(??)
暂时不懂 有空再弄
堆排序是不同的选择排序。

你可能感兴趣的:(JavaScript 排序算法)