javascript排序算法(1)

24 阅读5分钟
1,比较相邻的元素,如果第一个比第二个大,交换他们两个
2,对每一对相邻元素作同样的工作,从开始第一对到结尾最后一对,这样在最后的元素应该会是最大的
3,针对所有元素重复以上步骤,除了最后一个
4,重复1-3 ,直到排序完成
function bubbleSort(arr) {
 var len = arr.length;
 for(var i=0; i<len; i++) {
    for(var j=0; j<len-1; j++) {
    // 相邻的两个元素作比较,如果第一个元素比第二个元素大进行交换
      if(arr[j] > arr[j+1]) {
          // 交换元素
        var temp = arr[j+1];
          arr[j+1] = arr[j];
          arr[j] = temp;
      }
    }
 }
    return arr;
}
var arr = [3,44,38,5,47,12,43,344,32,44,3423,4,54,32,1213,4343,87,97,65];
console.log(bubbleSort(arr))

// 改进冒泡排序
function bubbleSort2(arr) {
    console.time('改进后冒泡排序耗时');
    var i = arr.length-1;  //初始时,最后位置保持不变
    while ( i> 0) {
        var pos= 0; //每趟开始时,无记录交换
        for (var j= 0; j< i; j++)
            if (arr[j]> arr[j+1]) {
                pos= j; //记录交换的位置
                var tmp = arr[j]; arr[j]=arr[j+1];arr[j+1]=tmp;
            }
        i= pos; //为下一趟排序作准备
     }
     console.timeEnd('改进后冒泡排序耗时');
     return arr;
}
var arr=[3,44,38,5,47,15,36,26,27,2,46,4,19,50,48];
console.log(bubbleSort2(arr));//[2, 3, 4, 5, 15, 19, 26, 27, 36, 38, 44, 46, 47, 48, 50]


// 改进3冒泡排序
function bubbleSort(arr) {
    var low = 0;
    var high = arr.length - 1; // 设置变量的初始值
    var temp,j;
    while(low < high) {
        // 正向冒泡寻找最大者
        for(j=low; j < high; ++j)
            if(arr[j] > arr[j+1]) {
                temp = arr[j];
                arr[j] = arr[j+1];
                arr[j+1]=temp;
            }
        // 修改high值,找到最大者
        --high;
        // 反向冒泡,找到最小者
        for(j = high; j < low; --j) {
            if(arr[j] < arr[j-1]) {
                temp = arr[j];
                arr[j] = arr[j-1];
                arr[j-1] = temp;
            }
            // 修改low值,后移一位
            ++low;
        }
        return arr;
    }
}

这里写图片描述

<1>.初始状态:无序区为R[1..n],有序区为空;
<2>.第i趟排序(i=1,2,3...n-1)开始时,当前有序区和无序区分别为R[1..i-1]和R(i..n)。该趟排序从当前无序区中-选出关键字最小的记录 R[k],将它与无序区的第1个记录R交换,使R[1..i]和R[i+1..n)分别变为记录个数增加1个的新有序区和记录个数减少1个的新无序区;
<3>.n-1趟结束,数组有序化了。
function selectionSort(arr) {
    var len = arr.length;
    var minIndex,temp;
    for(var i = 0; i <len-1; 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;
}

这里写图片描述

 1,从第一个元素开始,该元素可以被认为已经排序
 2, 取出下一个元素
 <2>.取出下一个元素,在已经排序的元素序列中从后向前扫描;
<3>.如果该元素(已排序)大于新元素,将该元素移到下一位置;
<4>.重复步骤3,直到找到已排序的元素小于或者等于新元素的位置;
<5>.将新元素插入到该位置后;
<6>.重复步骤2~5。
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 binaryInsertionSort(array) {
    if(Object.prototype.toString.call(array).slice(8,-1) === 'Array') {
        for(var i=1; i<array.length; i++) {
            var key = array[i], left = 0; right = i - 1;
            while(left <= right) {
                var middle = parseInt((left + right) / 2);
                if(key < array[middle]) {
                    right = middle - 1;
                }else {
                    left = middle + 1;
                }
            }
            for(var j = i - 1; j >= left; j--) {
                array[j + 1] = array[j];
            }
            array[left] = key;
        }
        return array;
    }else {
        return 'array is not an Array';
    }
}

这里写图片描述

先将整个待排序的记录序列分割成为若干子序列分别进行直接插入排序,具体算法描述:

<1>. 选择一个增量序列t1,t2,…,tk,其中ti>tj,tk=1;
<2>.按增量序列个数k,对序列进行k 趟排序;
<3>.每趟排序,根据对应的增量ti,将待排序列分割成若干长度为m 的子序列,分别对各子表进行直接插入排序。仅增量因子为1 时,整个序列作为一个表来处理,表长度即为整个序列的长度。

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

这里写图片描述

<1>.把长度为n的输入序列分成两个长度为n/2的子序列;
<2>.对这两个子序列分别采用归并排序;
<3>.将两个排序好的子序列合并成一个最终的排序序列。

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 mergee(left,right) {
    var result = [];
    while(left.length && right.length) {
        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;
}

这里写图片描述

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

1,方法一
function quickSort(array,left,right) {
    if(Object.prototype.toString.call(array).slice(8, -1) === 'Array' && typeof left === 'number' && typeof right === 'number') {
        if(left < right) {
            var x = array[right],i=left - 1, temp;
            for(var j = left; j<= right; j++) {
                if(array[j] <= x) {
                    i++;
                    temp = array[i];
                    array[i] = array[j];
                    array[j] = temp;
                }
            }
            quickSort(array,left, i-1);
            quickSort(array, i + 1, right);
        }
        return array;
    }else {
        return 'array os not an Array or left or right is not a number'
    }
}

快速排序

堆排序
<1>.将初始待排序关键字序列(R1,R2....Rn)构建成大顶堆,此堆为初始的无序区;
<2>.将堆顶元素R[1]与最后一个元素R[n]交换,此时得到新的无序区(R1,R2,......Rn-1)和新的有序区(Rn),且满足R[1,2...n-1]<=R[n];
<3>.由于交换后新的堆顶R[1]可能违反堆的性质,因此需要对当前无序区(R1,R2,......Rn-1)调整为新堆,然后再次将R[1]与无序区最后一个元素交换,得到新的无序区(R1,R2....Rn-2)和新的有序区(Rn-1,Rn)。不断重复此过程直到有序区的元素个数为n-1,则整个排序过程完成。
function heapSort(array) {
    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);
        }
        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]

这里写图片描述