zoukankan      html  css  js  c++  java
  • 算法:基于比较的排序算法

    最近整理了常用的排序算法,整理好,留下自己的思考过程。

    1、冒泡排序:

    (1)平均时间复杂度:O(n2)

    (2)最好时间复杂度:O(n)

    (3)最坏时间复杂度:O(n2)

    (5)空间复杂度:O(1)

    (5)稳定性:稳定

    (6)JavaScript实现:

    function bubble ( arr ) {
        var len = arr.length;
        var tmp;
        //  外层循环负责控制排序的趟数
        for(var i = 0; i < len - 1; i++){
           // 内层循环负责进行一趟排序
           for(var j = 0; j < len - 1 - i; j++){
              if(arr[j + 1] < arr[j]){
                  tmp = arr[j];
                  arr[j] = arr[j + 1];
                  arr[j + 1] = tmp;
              };
           };
        };
        return arr;
    };

    2、选择排序:

    (1)平均时间复杂度:O(n2)

    (2)最好时间复杂度:O(n2)

    (3)最坏时间复杂度:O(n2)

    (4)空间复杂度:O(1)

    (5)稳定性:不稳定

    (6)JavaScript实现:

    function select( arr ) {
       var len = arr.length;
       // 外层循环需要进行len - 1趟排序
       for(var i = 0; i < len - 1; i++){
          var index = i;
          var min = arr[i];
          var tmp;
          // 内层循环从未排序的数组元素中比较出最小的一个
          for(var j = i + 1; j < len; j++){
             if(min > arr[j]){
                index = j;
                min = arr[j];
             };
          };
          // 将其放在排序后的数组元素的最后
          tmp = arr[i];
          arr[i] = min;
          arr[index] = tmp;
       };
    };

    3、插入排序:

    (1)平均时间复杂度:O(n2)

    (2)最好时间复杂度:O(n)

    (3)平均时间复杂度:O(n2)

    (4)空间复杂度:O(1)

    (5)稳定性:稳定

    (6)JavaScript实现:

    function insert ( arr ) { 
       var len = arr.length;
       var tmp;
       for(var i = 1; i < len; i++){
          // 取出当前的数组元素
          tmp = arr[i];
          for(var j = i - 1; j >= 0; j--){
             if (arr[j] > tmp) {
                arr[j+1] = arr[j];
             } else {
           break;
         }; };
    // 插入取出的数组元素 arr[j+1] = tmp; }; return arr; }

     4、希尔排序:

    (1)平均时间复杂度:O(nlogn) ~ O(n2)

    (2)最好时间复杂度:O(n1.3)

    (3)最坏时间复杂度:O(n2)

    (4)空间复杂度:O(1)

    (5)稳定性:不稳定

    (6)JavaScript实现:

    // 插入排序
    function sort( arr, di ){
       for(var i = di; i < arr.length; i++){
          var guard = arr[i];
          for(var j =i -di; j >= 0 && guard < arr[j]; j -= di){
             arr[j+di] = arr[j];
          };
          arr[j+di] = guard;
       };
       return arr;
    }
    
    //  希尔排序,本质上是以不同的步长多次进行插入排序
    //  步长的选择对希尔排序的效率有显著影响
    function shell ( arr ) {
      var di = parseInt( arr.length / 2 );
      while ( di >= 1) {
          arr = sort( arr, di);
          di = parseInt( di / 2 );
      };
      return arr;
    };

    5、归并排序:

    (1)平均时间复杂度:O(nlogn)

    (2)最好时间复杂度:O(nlogn)

    (3)最坏时间复杂度:O(nlogn)

    (4)空间复杂度:O(n)

    (5)稳定性:稳定

    (6)JavaScript实现:

    // 对被归并的左右两个数组进行归并排序
    // 被输入的左右两个数组,都是有序的。
    function merge (left, right){
       var l = 0,
             r = 0;
       var result = [];
       // 对左右两个数组的首项,进行比较,较小的推入栈中。
       while(l < left.length && r < right.length){
          if(left[l] < right[r]){
             result.push( left[l] );
             l += 1;
          } else {
             result.push( right[r] );
             r += 1;
          };
       };
       // 经过上面的比较,左右两个数组,必定有一个数组比较完毕,一个没有比较完毕。
       // 但是,在不同情况的递归层,有不同的表现,故而将二者未比较的元素都连接到result中。
       // 由于,左右两个数组在输入前就是有序的,剩余未经比较的数组元素也是有序的,且都大于之前经过比较的数组元素,故而可以将其连接到result。
       // 下方的代码,实质上是将左右数组中,未经比较的数组元素连接到result。
       result = result.concat( left.slice(l) );
       result = result.concat( right.slice(r) );
       return result;
    };
    
    function mergeSort ( arr ){
       var len = arr.length;
       // 结束递归
       if(len <= 1){
          return arr;
       };
       // 切割数组,并对切割后的数组进行递归操作
       var middle = Math.floor( len/2 );
       var left = mergeSort( arr.slice(0, middle) );
       var right = mergeSort( arr.slice(middle) );
       // 完成递归后,进行归并
       return merge(left, right);
    }

    6、快速排序:

    (1)平均时间复杂度:O(nlogn)

    (2)最好时间复杂度:O(nlogn)

    (3)最坏时间复杂度:O(n2)

    (4)空间复杂度:O(logn) ~ O(n)

    (5)稳定性:不稳定

    (6)JavaScript实现:

    function quick ( arr ) {
       var less = [],
             pivotList = [],
             more = [],
             result = [],
             len = arr.length;
       // 结束递归
       if(len <= 1){
           return arr;
       };
    
       // 与基准对比,将数组划分为小,中,大三组
       var pivot = arr[0];
       for(var i = 0; i <len; i++){
          if(arr[i] < pivot){
             less.push(arr[i]);
          } else if(arr[i] > pivot){
             more.push(arr[i]);
          } else {
             pivotList.push(arr[i]);
          };
       };
       // 递归地对划分出的小、大两个组进行快速排序
       less = quick(less);
       more = quick(more);
       // 将排序好的小,中,大三组连接起来 
       result = result.concat(less, pivotList, more);
       return result;
    }
  • 相关阅读:
    【转】算法的时间复杂度
    FFT 物理意义(转)
    【转】FIR学习1
    【转】DFT DTFT DFS FFT的关系
    【转】TCL中的数组
    【转】setup time和hold time的周期问题(slack)
    【转】TCL语法简介
    【转】亚稳态分析
    ubuntu下Samba服务器搭建
    第一次生成uImage出现的问题解决
  • 原文地址:https://www.cnblogs.com/niconicohang/p/6618492.html
Copyright © 2011-2022 走看看