Men的博客

欢迎光临!

0%

算法之排序

冒泡排序

思想:每次遍历,相邻两个比较大小,修改位置
复杂度:n平方
function maopao(arr) {
    for (var i = 0; i < arr.length; i++) {
        for (var j = 0; j < arr.length; j++) {
            if (arr[i] > arr[j]) {
                var temp = arr[i];
                arr[i] = arr[j];
                arr[j] = temp;
            }
        }
    }
}

选择排序

思想:一次便利结束后,找到最小的,放到最前面,交换次数较冒泡排序少
排序复杂度:n平方
function xuanze(arr) {
    for (var i = 0; i < arr.length; i++) {
        var min = i;
        for (var j = 0; j < arr.length; j++) {
            if (arr[j] <arr[i]) {
                min = j;
            }
        }
        if (min != i) {
            var temp = arr[i];
            arr[i] = arr[min];
            arr[min] = arr[i];
        }
    }
}

插入排序

思想:每次往最小数组里插入一个数据,并保证数组是排序的
(1) 将这个序列的第一个元素R0视为一个有序序列; 
(2) 依次把 , , … ,  插入到这个有序序列中; 
(3) 将插入到有序序列中时,前 i-1 个数是有序的,将和 ~ 从后往前进行比较,确定要插入的位置。
function insertSort(arr) {
    var len = arr.length;
    var preIndex,current;
    for (var i = 1; i < len; i++) {
        preIndex = i -1;
        current = arr[i];
        while(preIndex >=0 && arr[preIndex] > current) {
            arr[preIndex +1] = arr[preIndex];
            preIndex --;
        }
        arr[preIndex +1] = current;
    }
}

希尔排序

4.希尔排序,希尔排序也是一种插入排序
不同:希尔排序优先比较较远的元素,希尔排序的核心在于间隔序列的设定
对于n个待排序的数列,取一个小于n的整数gap(gap被称为步长)将待排序元素
分成若干个组子序列,所有距离为gap的倍数的记录放在同一个组中;然后,对
各组内的元素进行直接插入排序。 这一趟排序完成之后,每一个组的元素都是
有序的。然后减小gap的值,并重复执行上述的分组和排序。重复这样的操作,
当gap=1时,整个数列就是有序的。
function shellSort(arr) {
    var len = arr.length;
    var temp,gap =1;
    while(gap < len/3){
        gap = gap *3 +1;
    }
    for (gap; gap> 0; gap = Math.floor(gap/3)) {
        for (var i = gap; i < len; i++) {
            temp = arr[i];
            for (var j = i - gap; j >0 && arr[j] > temp; j -= gap) {
                arr[j+gap] = arr[j];
            }
            arr[j+gap] = temp;
        }
    }
    return arr;
}

归并排序

作为一种典型的分而治之思想的算法应用
将一个数组排序,可以先递归的将它分成两半分别排序,然后再将结果归并起来。
缺点:需要额外的空间
从下往上的归并排序:将待排序的数列分成若干个长度为1的子数列,然后将这
些数列两两合并;得到若干个长度为2的有序数列,再将这些数列两两合并;得
到若干个长度为4的有序数列,再将它们两两合并;直接合并成一个数列为止。
这样就得到了我们想要的排序结果
function mergeSort(arr) {  //采用自上而下的递归方法
    var len = arr.length;
    if(len < 2) {
        return arr;
    }
    var middle = Math.floor(len / 2),
        left = arr.slice(0, middle),
        right = arr.slice(middle);
    return merge(mergeSort(left), mergeSort(right));
}

function merge(left, right)
{
    var result = [];

    while (left.length>0 && right.length>0) {
        if (left[0] <= right[0]) {
            result.push(left.shift());
        } else {
            result.push(right.shift());
        }
    }

    while (left.length)
        result.push(left.shift());

    while (right.length)
        result.push(right.shift());

    return result;
}

快速排序(Quick Sort)

分而治之思想在排序算法。本质上来看,快速排序应该算是在冒泡排序基础上的递归分治法。
先是把第一个挖出来,作为基值;然后先是从右向左,对比基值,如果如果小,那么放到坑里;然后在从左往右对比基值,如果大,那么放到坑里;当换完一轮了后,把基值放到坑里;然后在根据基值,分左右两组,递归排序;
通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比
另外一部分的所有数据都要小,继续对长度较短的序列进行同样的分割,最后到
达整体有序。在排序过程中,由于已经分开的两部分的元素不需要进行比较,故
减少了比较次数,降低了排序时间。
function quickSort(arr, left, right) {
    var len = arr.length,
        partitionIndex,
        left = typeof left != 'number' ? 0 : left,
        right = typeof right != 'number' ? len - 1 : right;

    if (left < right) {
        partitionIndex = partition(arr, left, right);
        quickSort(arr, left, partitionIndex-1);
        quickSort(arr, partitionIndex+1, right);
    }
    return arr;
}

function partition(arr, left ,right) {     //分区操作
    var pivot = left,                      //设定基准值(pivot)
        index = pivot + 1;
    for (var i = index; i <= right; i++) {
        if (arr[i] < arr[pivot]) {
            swap(arr, i, index);
            index++;
        }        
    }
    swap(arr, pivot, index - 1);
    return index-1;
}

function swap(arr, i, j) {
    var temp = arr[i];
    arr[i] = arr[j];
    arr[j] = temp;
}

堆排序(Heap Sort)

堆排序可以说是一种利用堆的概念来排序的选择排序。分为两种方法:
大顶堆:每个节点的值都大于或等于其子节点的值,在堆排序算法中用于升序排列
小顶堆:每个节点的值都小于或等于其子节点的值,在堆排序算法中用于降序排列
堆排序的基本思想是:将待排序序列构造成一个大顶堆,此时,整个序列的最大
值就是堆顶的根节点。将其与末尾元素进行交换,此时末尾就为最大值。然后将
剩余n-1个元素重新构造成一个堆,这样会得到n个元素的次小值。如此反复执
行,便能得到一个有序序列了

var len;    //因为声明的多个函数都需要数据长度,所以把len设置成为全局变量

function buildMaxHeap(arr) {   //建立大顶堆
    len = arr.length;
    for (var i = Math.floor(len/2); i &gt;= 0; i--) {
        heapify(arr, i);
    }
}

function heapify(arr, i) {     //堆调整
    var left = 2 * i + 1,
        right = 2 * i + 2,
        largest = i;

    if (left < len && arr[left] > arr[largest]) {
        largest = left;
    }

    if (right < len && arr[right] > arr[largest]) {
        largest = right;
    }

    if (largest != i) {
        swap(arr, i, largest);
        heapify(arr, largest);
    }
}

function swap(arr, i, j) {
    var temp = arr[i];
    arr[i] = arr[j];
    arr[j] = temp;
}

function heapSort(arr) {
    buildMaxHeap(arr);

    for (var i = arr.length-1; i > 0; i--) {
        swap(arr, 0, i);
        len--;
        heapify(arr, 0);
    }
    return arr;
}