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;
    }
  • 相关阅读:
    监控里的主码流和子码流是什么意思
    监控硬盘容量计算
    一个能让你了解所有函数调用顺序的Android库
    电工选线
    oracle linux dtrace
    list all of the Oracle 12c hidden undocumented parameters
    Oracle Extended Tracing
    window 驱动开发
    win7 x64 dtrace
    How to Use Dtrace Tracing Ruby Executing
  • 原文地址:https://www.cnblogs.com/niconicohang/p/6618492.html
Copyright © 2011-2022 走看看