前端排序算法汇总

冒泡排序

冒泡排序的原理如下,从第一个元素开始,把当前元素和下一个索引元素进行比较。如果当前元素大,那么就交换位置,重复操作直到比较到最后一个元素,那么此时最后一个元素就是该数组中最大的数。下一轮重复以上操作,但是此时最后一个元素已经是最大数了,所以不需要再比较最后一个元素,只需要比较到 length - 1 的位置。以此类推,每一次最外层循环都会将后面的数排好序,因此里面的循环可以减少i次循环.

冒泡排序算法时间复杂度为O(n*n)

bubble.gif

//算法实现
function bubble(array){
   let len = array.length;
   if(len <= 0){return false;}
   for(let i = 0;i < len;i++){
       //由于后面的数已经排好序了,因此第二次没必要再循环len次,而是len-i次
       for(let j = 0; j < len - 1 - i;j++){  
           if(array[j] > array[j+1]){
               [array[j], array[j+1]] = [array[j+1], array[j]];
           }
       }
   }
}

选择排序

选择排序的原理如下:先将一个值的索引设置为最小索引minIndex,通常设置是第一个值,然后将最小索引的值与其他值进行比较,若最小索引值比其他的值要大,则将最小索引设置为该值的下标,然后最小索引的值与该值交换。

选择排序的时间复杂度是O(n*n)

selection.gif

function selection(array){
    let len = array.length;
    if(len <= 0){return false;}
    for(let i = 0; i < len; i++){
        let minIndex = i;
        for(let j = i + 1;j < len;j++){
            //索引的互换,minIndex可能会多次变化
            minIndex = array[j] < array[minIndex] ? j : minIndex;
        }
        //值的互换
        [array[i], array[minIndex]]  = [array[minIndex], array[i]];
    }
}

插入排序

插入排序的原理:默认第一个元素已经排好序,外层从第二个元素开始循环,里层循环从第一个元素开始,若里层循环满足条件,则交换值。里层循环将会进行多次比较

插入排序的时间复杂度为O(n*n)

insert.gif

function insert(array){
    let len = array.length;
    if(len<=0){return false;}
    for(let i = 1; i < len; i++){
        for(let j = i - 1; j >= 0 && array[j] > array[j+1]; j--){
            [array[j], array[j+1]]  = [array[j+1], array[j]];
        }
    }
}

归并排序

归并排序的原理如下。递归的将数组两两分开直到最多包含两个元素,然后将数组排序合并,最终合并为排序好的数组。假设我有一组数组 [2,7,5,6,1,4,3],中间数索引是 3,先排序数组 [2,7,5,6] 。在这个左边数组上,继续拆分直到变成数组包含两个元素(如果数组长度是奇数的话,会有一个拆分数组只包含一个元素)。然后排序数组 [2,7][5,6] ,然后再排序数组 [2,7,5,6] ,这样左边数组就排序完成,然后按照以上思路排序右边数组,最后将数组 [2, 7, 5, 6][1, 3, 4] 排序。

归并排序的时间复杂度为O(N*logN)

guibing.gif

function sort(array){
    let len = array.length;
    if(len <=0){return;}
    mergeSort(array, 0, len - 1);
}
function mergeSort(array, left, right){
    if(left === right) {return;}
    //位运算更安全,不会溢出,相当于left+(right-left)/2
    let mid = parseInt(left + ((right - left) >> 1));
    mergeSort(array, left, mid);
    mergeSort(array, mid+1, right);
    let temp = [], i = 0, p1 = left, p2 = mid+1;
    while(p1 <= mid && p2 <= right){
        temp[i++] = array[p1] < array[p2] ? array[p1++] : array[p2++];
    }
    while(p1 <= mid){
        temp[i++] = array[p1++];
    }
    while(p2 <= right){
        temp[i++] = array[p2++];
    }
    for(let i = 0; i < temp.length; i++){
        array[left + i] = temp[i];
    }
    return array;
}

快速排序

快排的原理如下。随机选取一个数组中的值作为基准值,如最右侧的值,从左至右取值与基准值对比大小。比基准值小的放数组左边,大的放右边,对比完成后将基准值和第一个比基准值大的值交换位置。然后将数组以基准值的位置分为两部分,继续递归以上操作

快速排序的时间复杂度为O(N*logN)

quite.gif

function quickSort(array){
     let len = array.length;
     if(len < 0){return;}
     quick(array, 0, array.length-1);
}
 function quick(array, left, right){
     let index;
     if(array.length > 1){
         index = partition(array, left, right);
         if(left < index - 1){
             quick(array, left, index - 1);
         }
         if(index < right){
             quick(array, index, right);
         }
     }
 }
function partition(array, left, right){
     let pivot = array[Math.floor((right + left) / 2)];  //选取中间的元素作为主元
     let i = left, j = right;
     while(i <= j){
         while(array[i] < pivot){
             i++;
         }
         while(array[j] > pivot){
             j--;
         }
         if(i <= j){
             [array[i], array[j]] = [array[j], array[i]];
             i++;
             j--;
         }
     }
     return i;
 }

堆排序

堆也可以作为一种 数据结构,通常情况下,堆被嵌入到储存数列的排序中,并且只通过交换数字来完成排序

dui0.gif

堆排序利用了二叉堆的特性来做,二叉堆通常用数组表示,并且二叉堆是一颗完全二叉树(所有叶节点(最底层的节点)都是从左往右顺序排序,并且其他层的节点都是满的)

dui.gif

function heapSort(array) {
   function maxHeapify(array, index, heapSize) {
       let iMax, iLeft, iRight;
       while (true) {
           iMax = index;
           iLeft = 2 * index + 1;
           iRight = 2 * (index + 1);
           if (iLeft < heapSize && array[index] < array[iLeft]) {
               iMax = iLeft;
           }
           if (iRight < heapSize && array[iMax] < array[iRight]) {
               iMax = iRight;
           }
           if (iMax !== index) {
               //swap(array, iMax, index);
               [array[iMax], array[index]] = [array[index], array[iMax]];
               index = iMax;
           } else {
               break;
           }
       }
   }
   function buildMaxHeap(array) {
       let i, iParent = Math.floor(array.length / 2) - 1;
       for (i = iParent; i >= 0; i--) {
           maxHeapify(array, i, array.length);
       }
   }
   function sort(array) {
       buildMaxHeap(array);
       for (let i = array.length - 1; i > 0; i--) {
           //swap(array, 0, i);
           [array[0], array[i]] = [array[i], array[0]];
           maxHeapify(array, 0, i);
       }
       return array;
   }
   return sort(array);
}
  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值