美文网首页
排序之二--整理

排序之二--整理

作者: Creator93 | 来源:发表于2018-03-21 22:48 被阅读0次

    算法的基本

    首先说明算法的优劣的区别:
    稳定与不稳定:若a原本在b的前面,而且a=b;排序之后a在b前面就是稳定的,在b后面就是不稳定的。
    内排序:所有排序操作都是在内存中完成的。
    重要的时间复杂度和空间复杂度:
    ①时间复杂度:一个算法执行所耗费的时间。
    ②空间复杂度:运行完一个程序所需内存的大小。
    上图对比记忆


    image.png

    图片中的名词解释(
    n:数据规模,
    k:“桶”的个数,
    In-place:占用常数内存,不占用额外的内存,
    out-place:占用额外的内存

    排序的分类有几种。

    内部排序{
          插入排序{
                  直接插入排序
                  希尔排序
          }
         选择排序{
                  简单选择排序
                  堆排序
          }
         交换排序{
                  冒泡排序
                  快速排序
          }
         归并排序
         基数排序
    }
    外部排序
    

    实现

    ①冒泡
    排序之初,冒泡排序,之前就写过这里复习一下。一二比较,二三比较。。。按要求的顺序,从小到达排序,那么比较之后大的往后放,从头到尾依次进行。通过比较,最大或者最小的会一步一步的“浮出水面”。
    代码js实现复习。

    var arr  = new Array(49,38,65,97,76,13,27,49,78,34,12,64,5,4,62,99,98,54,56,17,18,23,34,15,35,25,53,51);
       console.log(arr);
       for (var i = 0; i <arr.length-1; i++) {
           for (var j = 0; j < arr.length-1-i;j++) {
               var temp = 0;
               if(arr[j]>arr[j+1]){
                   temp = arr[j];
                   arr[j] = arr[j+1];
                   arr[j+1] = temp;
               }
           }       
       }
       console.log(arr);
    //[4, 5, 12, 13, 15, 17, 18, 23, 25, 27, 34, 34, 35, 38, 49, 49, 51, 53, 54, 56, 62, 64, 65, 76, 78, 97, 98, 99]
    
    时间复杂度最好O(n),最差为O(n²)平均为O(n²)空间复杂度为O(1)稳定。
    

    ②选择排序:先从未排序的序列中找到最小的,存放在头部,然后在剩余的序列中再找最小的,。。。依次。。

    function selectSort(arr){
            var len = arr.length;
            var minIndex,temp;
            for(var i=0;i<len;i++){
                minIndex = i;
                for(var j = i+1;j<len;j++){
                    if(arr[j]<arr[minIndex]){
                        minIndex = j;
                    }
                }
                temp = arr[i];
                arr[i] = arr[minIndex];
                arr[minIndex] = temp;
            }
            return arr;
        }
        var arr = new Array(2,123,4,12,123,6);
        console.log(selectSort(arr));
    //[2, 4, 6, 12, 123, 123]
    

    因为不管如何时间复杂度都是O(n²),空间复杂度为O(1);所以数据规模越小越好。

    ③插入排序
    对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。插入排序在实现上,通常采用in-place排序(即只需用到O(1)的额外空间的排序),因而在从后向前扫描过程中,需要反复把已排序元素逐步向后挪位,为最新元素提供插入空间。

    function insertionSort(array) {
        if (Object.prototype.toString.call(array).slice(8, -1) === 'Array') {
          
            for (var i = 1; i < array.length; i++) {
                var key = array[i];
                var j = i - 1;
                while (j >= 0 && array[j] > key) {
                    array[j + 1] = array[j];
                    j--;
                }
                array[j + 1] = key;
            }
            return array;
        } else {
            return 'array is not an Array!';
        }
    }
    

    ④希尔排序
    希尔排序是插入排序的一种更高效率的实现。它与插入排序的不同之处在于,它会优先比较距离较远的元素。希尔排序的核心在于间隔序列的设定。既可以提前设定好间隔序列,也可以动态的定义间隔序列。

    function shellSort(arr) {
        var len = arr.length,
            temp,
            gap = 1;
        while(gap < len/5) {          //动态定义间隔序列
            gap =gap*5+1;
        }
        for (gap; gap > 0; gap = Math.floor(gap/5)) {
            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;
    }
    var arr=[3,44,38,5,47,15,36,26,27,2,46,4,19,50,48];
    //[2, 3, 4, 5, 15, 19, 26, 27, 36, 38, 44, 46, 47, 48, 50]
    

    ⑤归并排序
    归并排序是建立在归并操作上的一种有效的排序算法。该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。归并排序是一种稳定的排序方法。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为2-路归并。
    和选择排序一样,归并排序的性能不受输入数据的影响,但表现比选择排序好的多,因为始终都是O(n log n)的时间复杂度。代价是需要额外的内存空间

    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;
    }
    

    ⑥快速排序
    快速排序的基本思想:通过一趟排序将待排记录分隔成独立的两部分,其中一部分记录的关键字均比另一部分的关键字小,则可分别对这两部分记录继续进行排序,以达到整个序列有序。

    从数列中挑出一个元素,称为 “基准”(pivot); <2>.重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准值大的摆在基准的后面(相同的数可以到任一边)。在这个分区退出之后,该基准就处于数列的中间位置。这个称为分区(partition)操作; <3>.递归地(recursive)把小于基准值元素的子数列和大于基准值元素的子数列排序

    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 quickSort2(left).concat([pivot], quickSort2(right));
    };
    
    var arr=[3,44,38,5,47,15,36,26,27,2,46,4,19,50,48];
    console.log(quickSort(arr));//[2, 3, 4, 5, 15, 19, 26, 27, 36, 38, 44, 46, 47, 48, 50]
    

    ⑦堆排序
    堆排序(Heapsort)是指利用堆这种数据结构所设计的一种排序算法。堆积是一个近似完全二叉树的结构,并同时满足堆积的性质:即子结点的键值或索引总是小于(或者大于)它的父节点。

    *方法说明:堆排序
    @param  array 待排序数组*/
    function heapSort(array) {
        console.time('堆排序耗时');
        if (Object.prototype.toString.call(array).slice(8, -1) === 'Array') {
            //建堆
            var heapSize = array.length, temp;
            for (var i = Math.floor(heapSize / 2) - 1; i >= 0; i--) {
                heapify(array, i, heapSize);
            }
     
            //堆排序
            for (var j = heapSize - 1; j >= 1; j--) {
                temp = array[0];
                array[0] = array[j];
                array[j] = temp;
                heapify(array, 0, --heapSize);
            }
            console.timeEnd('堆排序耗时');
            return array;
        } else {
            return 'array is not an Array!';
        }
    }
    /*方法说明:维护堆的性质
    @param  arr 数组
    @param  x   数组下标
    @param  len 堆大小*/
    function heapify(arr, x, len) {
        if (Object.prototype.toString.call(arr).slice(8, -1) === 'Array' && typeof x === 'number') {
            var l = 2 * x + 1, r = 2 * x + 2, largest = x, temp;
            if (l < len && arr[l] > arr[largest]) {
                largest = l;
            }
            if (r < len && arr[r] > arr[largest]) {
                largest = r;
            }
            if (largest != x) {
                temp = arr[x];
                arr[x] = arr[largest];
                arr[largest] = temp;
                heapify(arr, largest, len);
            }
        } else {
            return 'arr is not an Array or x is not a number!';
        }
    }
    var arr=[91,60,96,13,35,65,46,65,10,30,20,31,77,81,22];
    console.log(heapSort(arr));//[10, 13, 20, 22, 30, 31, 35, 46, 60, 65, 65, 77, 81, 91, 96]
    

    ⑧计数排序
    计数排序(Counting sort)是一种稳定的排序算法。计数排序使用一个额外的数组C,其中第i个元素是待排序数组A中值等于i的元素的个数。然后根据数组C来将A中的元素排到正确的位置。它只能对整数进行排序。

    function countingSort(array) {
        var len = array.length,
            B = [],
            C = [],
            min = max = array[0];
        console.time('计数排序耗时');
        for (var i = 0; i < len; i++) {
            min = min <= array[i] ? min : array[i];
            max = max >= array[i] ? max : array[i];
            C[array[i]] = C[array[i]] ? C[array[i]] + 1 : 1;
        }
        for (var j = min; j < max; j++) {
            C[j + 1] = (C[j + 1] || 0) + (C[j] || 0);
        }
        for (var k = len - 1; k >= 0; k--) {
            B[C[array[k]] - 1] = array[k];
            C[array[k]]--;
        }
        console.timeEnd('计数排序耗时');
        return B;
    }
    var arr = [2, 2, 3, 8, 7, 1, 2, 2, 2, 7, 3, 9, 8, 2, 1, 4, 2, 4, 6, 9, 2];
    console.log(countingSort(arr)); //[1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 4, 4, 6, 7, 7, 8, 8, 9, 9]
    

    ⑨桶排序

    相关文章

      网友评论

          本文标题:排序之二--整理

          本文链接:https://www.haomeiwen.com/subject/vgpnqftx.html