美文网首页
2019-06-10 排序算法

2019-06-10 排序算法

作者: DreamNeverDie | 来源:发表于2019-06-11 19:22 被阅读0次
    0.公共方法
       function swap(arr,a,b){
               var tmp=arr[b];
               arr[b]=arr[a];
               arr[a]=tmp;
           }
    
         function generateRandomArray(n, rangeL, rangeR) {
             var arr = [];
             for (var i = 0; i < n; i++) {
             arr.push(Math.floor(Math.random() * (rangeR - rangeL + 1))+ rangeL)
         }
           return arr;
     }
          function generateNearlyOrderedArray(n,swapTimes){
               var arr=[];
               for(var i=0;i<n;i++){
                   arr[i]=i;
               }
               for(var i=0;i<swapTimes;i++){
                   var posx=Math.floor(Math.random()*n)
                   var posy=Math.floor(Math.random()*n)
                   swap(arr,posx,posy)
               }
               return arr;
          }
       function testSort(sortName, fn,arr,n) {
             var start = Date.now();
             console.log(start)
             fn(arr,n);
             var end = Date.now();
             console.log(end);
             var time = (end - start)/1000;
             if(!isSorted(arr,n))
             {
                 console.log("数组还未排序成功!")
                   return false;
             }
             console.log(sortName+": "+time+"秒");
           }
    
          function isSorted(arr, n) {
                 for (var i = 0; i < n - 1; i++) {
                   if (arr[i + 1] < arr[i])
                     return false;
                   return true;
                 }
            }
    
        function copyArray(arr){
               return arr.map(function(item){
                       return item;
               })
          }
     
    
    1. 选择排序
    
        function selectionSort(arr,n){
            for(var i=0;i<n;i++){
                var minIndex=i;
                for(var j=i+1;j<n;j++){
                    if(arr[j]<arr[minIndex])
                    minIndex=j
                }
                swap(arr,minIndex,i)
                
            }
        }
    
        var arrTest=[9,6,13,4,10,8,12]
        selectionSort(arrTest,arrTest.length)
        console.log(arrTest)
    
    2. 插入排序
            function insertionSort(arr, n) {
                if (arguments.length == 3) {
                    var l=arguments[1];
                    var r=arguments[2]
                    for (var i = l + 1; i <= r; i++) {
                        var e = arr[i];
                        var j = null
                        for (j = i; j > 0 && arr[j - 1] > e; j--) {
                            arr[j] = arr[j - 1]
                        }
                        arr[j] = e
                    }
                }
                else {
                    for (var i = 1; i < n; i++) {
                        var e = arr[i];
                        var j = null
                        for (j = i; j > 0 && arr[j - 1] > e; j--) {
                            arr[j] = arr[j - 1]
                        }
                        arr[j] = e
                    }
                }
    
            }
    
    3. 归并排序
    function mergeSort(arr, n) {
    
                __mergeSort(arr, 0, n - 1);
    
            }
    
    
            // 递归使用归并排序,对arr[l...r]的范围进行排序
            function __mergeSort(arr, l, r) {
    
                /*      if( l >= r )
                                return; */
                if (r - l <= 15) {
                    insertionSort(arr, l, r);
                    return;
                }
    
                var mid = Math.floor((l + r) / 2);
                __mergeSort(arr, l, mid);
                __mergeSort(arr, mid + 1, r);
                if (arr[mid] > arr[mid + 1])
                    __merge(arr, l, mid, r);
            }
    
            // 将arr[l...mid]和arr[mid+1...r]两部分进行归并
            function __merge(arr, l, mid, r) {
    
    
                var aux = [];
    
                for (var i = l; i <= r; i++)
                    aux[i - l] = arr[i];
    
                // 初始化,i指向左半部分的起始索引位置l;j指向右半部分起始索引位置mid+1
                var i = l, j = mid + 1;
                for (var k = l; k <= r; k++) {
    
                    if (i > mid) {  // 如果左半部分元素已经全部处理完毕
                        arr[k] = aux[j - l]; j++;
                    }
                    else if (j > r) {  // 如果右半部分元素已经全部处理完毕
                        arr[k] = aux[i - l]; i++;
                    }
                    else if (aux[i - l] < aux[j - l]) {  // 左半部分所指元素 < 右半部分所指元素
                        arr[k] = aux[i - l]; i++;
                    }
                    else {  // 左半部分所指元素 >= 右半部分所指元素
                        arr[k] = aux[j - l]; j++;
                    }
                }
    
            }
    
    4.1 原始版快速排序
    // 对arr[l...r]部分进行partition操作
    // 返回p, 使得arr[l...p-1] < arr[p] ; arr[p+1...r] > arr[p]
    function __partition(arr,  l,  r){
    
        var v = arr[l];
    
        var j = l; // arr[l+1...j] < v ; arr[j+1...i) > v
        for( var i = l + 1 ; i <= r ; i ++ )
            if( arr[i] < v ){
                j ++;
                swap( arr ,j ,i );
            }
    
        swap( arr , l , j);
    
        return j;
    }
    
    // 对arr[l...r]部分进行快速排序
    function __quickSort( arr,  l,  r){
    
        if( l >= r )
            return;
    
        var p = __partition(arr, l, r);
        __quickSort(arr, l, p-1 );
        __quickSort(arr, p+1, r);
    }
    
    function quickSort( arr,  n){
    
        __quickSort(arr, 0, n-1);
    }
    
    4.2 随机化取值快速排序
    function _partition( arr,  l,  r){
    
        // 随机在arr[l...r]的范围中, 选择一个数值作为标定点pivot
        swap( arr,l , Math.ceil(Math.random(r-l+1))+l );
    
        var v = arr[l];
        var j = l;
        for( var i = l + 1 ; i <= r ; i ++ )
            if( arr[i] < v ){
                j ++;
                swap( arr,j , i );
            }
    
        swap( arr,l , j);
    
        return j;
    }
    
    // 对arr[l...r]部分进行快速排序
    function _quickSort( arr,  l,  r){
    
        // 对于小规模数组, 使用插入排序进行优化
        if( r - l <= 15 ){
            insertionSort(arr,l,r);
            return;
        }
    
        var p = _partition(arr, l, r);
        _quickSort(arr, l, p-1 );
        _quickSort(arr, p+1, r);
    }
    
    function quickSort( arr,  n){
    
        _quickSort(arr, 0, n-1);
    }
    
    4.3 双路快速排序
    // 双路快速排序的partition
            // 返回p, 使得arr[l...p-1] < arr[p] ; arr[p+1...r] > arr[p]
                function _partition2( arr,  l,  r){
    
                // 随机在arr[l...r]的范围中, 选择一个数值作为标定点pivot
                swap(arr,l, Math.ceil(Math.random(r - l + 1)) + l);
                var v = arr[l];
    
                // arr[l+1...i) <= v; arr(j...r] >= v
                var i = l + 1, j = r;
                while (true) {
                    // 注意这里的边界, arr[i] < v, 不能是arr[i] <= v
                    // 思考一下为什么?
                    while (i <= r && arr[i] < v)
                        i++;
    
                    // 注意这里的边界, arr[j] > v, 不能是arr[j] >= v
                    // 思考一下为什么?
                    while (j >= l + 1 && arr[j] > v)
                        j--;
    
                    // 对于上面的两个边界的设定, 有的同学在课程的问答区有很好的回答:)
                    // 大家可以参考: http://coding.imooc.com/learn/questiondetail/4920.html
    
                    if (i > j)
                        break;
    
                    swap(arr,i,j);
                    i++;
                    j--;
                }
    
                swap(arr,l, j);
    
                return j;
            }
        function _quickSort( arr,  l,  r){
    
            // 对于小规模数组, 使用插入排序进行优化
            if (r - l <= 15) {
                insertionSort(arr, l, r);
                return;
            }
    
            // 调用双路快速排序的partition
            var p = _partition2(arr, l, r);
            _quickSort(arr, l, p - 1);
            _quickSort(arr, p + 1, r);
        }
    
            function quickSort( arr,  n){
    
            _quickSort(arr, 0, n - 1);
        }
    
    4.4递归的三路快速排序算法
            // 递归的三路快速排序算法
                function __quickSort3Ways( arr,  l,  r){
    
                // 对于小规模数组, 使用插入排序进行优化
                if (r - l <= 15) {
                    insertionSort(arr, l, r);
                    return;
                }
    
                // 随机在arr[l...r]的范围中, 选择一个数值作为标定点pivot
                swap(arr,l, Math.ceil(Math.random() * (r - l + 1)) + l);
    
                var v = arr[l];
    
                var lt = l;     // arr[l+1...lt] < v
                var gt = r + 1; // arr[gt...r] > v
                var i = l + 1;    // arr[lt+1...i) == v
                while (i < gt) {
                    if (arr[i] < v) {
                        swap(arr,i, lt + 1);
                        i++;
                        lt++;
                    }
                    else if (arr[i] > v) {
                        swap(arr,i, gt - 1);
                        gt--;
                    }
                    else { // arr[i] == v
                        i++;
                    }
                }
    
                swap(arr,l, lt);
    
                __quickSort3Ways(arr, l, lt - 1);
                __quickSort3Ways(arr, gt, r);
            }
    
                function quickSort3Ways( arr,  n){
    
                __quickSort3Ways(arr, 0, n - 1);
            }
    
    
    // 比较Merge Sort和双路快速排序和三路快排三种排序算法的性能效率
    // 对于包含有大量重复数据的数组, 三路快排有巨大的优势
    // 对于一般性的随机数组和近乎有序的数组, 三路快排的效率虽然不是最优的, 但是是在非常可以接受的范围里
    // 因此, 在一些语言中, 三路快排是默认的语言库函数中使用的排序算法。比如Java:)
    
    
    5 原地堆排序
            function heapSort(arr){
              function __shiftDown(arr,n,k){
                while(2*k+1<n){
                        let j=2*k+1;
                        if(j+1<n&& arr[j+1]> arr[j])
                            j+=1;
                        if(arr[k]>= arr[j])
                            break;
                        swap(arr,k,j)
                        k=j
                    }
              }
                for(let i=Math.floor(arr.length-1/2);i>=0;i--)
                    __shiftDown(arr,arr.length,i)
                
                for(let i=arr.length-1;i>0;i--){
                  swap(arr,0,i)
                  __shiftDown(arr,i,0)
                }         
            }
    

    相关文章

      网友评论

          本文标题:2019-06-10 排序算法

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