js十大排序算法(下)

快速排序

快速排序即找一基准,小于的放在左数组,大于的放在右数组,并连接,进行递归。

function quickSort(arr){
        if(arr.length<=1){//如果数组只有一个数,就直接返回;
            return arr;
        }
        var num=Math.floor(arr.length/2);//找到中间数的索引值,如果是浮点数,则向下取整
        var newValue=arr.splice(num,1);//找到中间数的值
        var left=[],right=[];
        for(var i=0;i<arr.length;i++){
            if(arr[i]<newValue){
                left.push(arr[i]);//基准点的左边的数传到左边数组
            }else{
                right.push(arr[i]);//基准点的右边的数传到右边数组
            }
        }
        return quickSort(left).concat(newValue,quickSort(right));//递归不断重复比较,concat即连接数组
    }
    console.log(quickSort([21,5,45,12,56,8]));

堆排序

堆排序类似完全二叉树。利用堆顶元素最大的性质(但同行之间顺序未排),将堆顶元素取出放入新数组(循环时len–,视为新数组)中,将堆底元素放置堆顶,并重构,循环。

var len;      
function buildMaxHeap(arr) {   //建堆  
    len = arr.length;  
    // [n/2-1]表示的是最后一个有子节点 (本来是n/2(堆从1数起),但是这里arr索引是从0开始,所以-1)  
    for (var i = Math.floor(len/2)-1; i>=0; i--) {  
        maxHeapify(arr, i);  
    }  
    //对每一个节点(非叶节点),做堆调整  
}  
function maxHeapify(arr, i) {     //堆调整  
    var left = 2*i+1,    
        right = 2*i+2,   
        largest = i;   //i为该子树的根节点  

    if (left < len && arr[left] > arr[largest]) {    
        largest = left;  
    }  

    if (right < len && arr[right] > arr[largest]) {  
        largest = right;  
    }  

    if (largest != i) {  //即上面的if中有一个生效了  
        swap(arr, i, largest);  //交换最大的为父节点  
        maxHeapify(arr, largest);  //交换后,原值arr[i](往下降了)(索引保存为largest),  
        //作为根时,子节点可能比它大,因此要继续调整  
    }    
}   
function swap(arr, i, j) {  
    var temp = arr[i];    
    arr[i] = arr[j];  
    arr[j] = temp;  
}   
function heapSort(arr) {  
    buildMaxHeap(arr);  
    for (var i = arr.length-1; i > 0; i--) {  
        swap(arr, 0, i);  
        len--;  
        maxHeapify(arr, 0);  
    }  
    return arr;  
}  

var arr = [46,12,33,72,68,19,80,33];
heapSort(arr)
console.log(' after: ' + arr);

计数排序

计数排序要求数据集必须是已确定范围的整数。
统计数组中每个值为i的元素出现的次数,存入数组C的第i项,填充数组。

function countingSort(arr, maxValue) {
    var bucket =new Array(maxValue + 1),
        sortedIndex = 0;
        arrLen = arr.length,
        bucketLen = maxValue + 1;
 
    for (var i = 0; i < arrLen; i++) {
        if (!bucket[arr[i]]) {
            bucket[arr[i]] = 0;
        }
        bucket[arr[i]]++;
    }
 
    for (var j = 0; j < bucketLen; j++) {
        while(bucket[j] > 0) {
            arr[sortedIndex++] = j;
            bucket[j]--;
        }
    }
 
    return arr;
}

桶排序

桶排序利用了空间换时间的思想。即假设输入数据服从均匀分布,将数据分到有限数量的桶里,每个桶再分别排序,依次取出桶中数据。

/**
 * 桶排序
 * @param {Array} arr
 * @param {Number} bucketSize
 */
function bucketSort(arr, bucketSize = 5) {
  if (arr.length < 2) return arr;

  const buckets = createBucket(arr, bucketSize);
  return sortBuckets(buckets);
}

/**
 * @description:
 * @param {Array} arr=待排序数据
 * @param {Number} bucketSize=桶大小
 * @return:
 */
function createBucket(arr, bucketSize) {
  let minValue = arr[0];
  let maxValue = arr[0];
  // 找出数据中最大值和最小值,根据桶的大小用来划分桶的个数和区间
  for (let i = 1; i < arr.length; i++) {
    if (arr[i] < minValue) {
      minValue = arr[i];
    } else if (arr[i] > maxValue) {
      maxValue = arr[i];
    }
  }

  // 桶的个数
  const bucketCount = Math.ceil((maxValue - minValue) / bucketSize);

  // 创建桶,用二维数组来存储
  const buckets = [];
  for (let i = 0; i <= bucketCount; i++) {
    buckets[i] = [];
  }

  // 计算把数据放到哪个桶
  for (let i = 0; i < arr.length; i++) {
    let bucketIndex = Math.floor((arr[i] - minValue) / bucketSize);
    buckets[bucketIndex].push(arr[i]);
  }
  return buckets;
}

/**
 * @description: 排序桶
 * @param {Array}  buckets
 * @return:
 */
function sortBuckets(buckets) {
  const sortArray = [];
  for (let i = 0; i < buckets.length; i++) {
    if (buckets[i] != null) {
      const sortBucket = insertionSort(buckets[i]);
      sortArray.push(sortBucket);
    }
  }
  return sortArray;
}

/**
 * @description: 插入排序
 * @param {Array} arr
 * @return: 排好序的arr
 */
function insertionSort(arr) {
  if (arr.length < 2) return arr;
  for (let i = 1; i < arr.length; i++) {
    let key = arr[i]; // 第一个元素已排好序,从第二个开始比较插入
    let j = i - 1;
    for (; j >= 0; j--) {
      if (arr[j] > key) {
        arr[j + 1] = arr[j]; // 比较,较大者,往后移
      } else {
        break;
      }
    }
    arr[j + 1] = key; // 插入对应的位置
  }
  return arr;
}

// 随机生成1000000个[1,100]区间内的整数
let arr1 = Array.from(
  { length: 1000000 },
  item => (item = Math.floor(Math.random() * Math.floor(100) + 1))
);

console.time("timer");
// console.log(`排序前的数据:${arr1}, 排序后的数据:${bucketSort(arr1, 5)}`);
bucketSort(arr1, 1); // 桶越小,排序越快,即桶个数越多,排序越快
console.timeEnd("timer");

基数排序

基数排序即按照键值的每位数字分配桶。
先按照个位分配10个桶中,后按顺序分到另一桶,再按照十位分配到10个桶中,进行循环。

var counter = [];
function radixSort(arr, maxDigit) {
    var mod = 10;
    var dev = 1;
    for (var i = 0; i < maxDigit; i++, dev *= 10, mod *= 10) {
        for(var j = 0; j < arr.length; j++) {
            var bucket = parseInt((arr[j] % mod) / dev);
            if(counter[bucket]==null) {
                counter[bucket] = [];
            }
            counter[bucket].push(arr[j]);
        }
        var pos = 0;
        for(var j = 0; j < counter.length; j++) {
            var value = null;
            if(counter[j]!=null) {
                while ((value = counter[j].shift()) != null) {
                      arr[pos++] = value;
                }
          }
        }
    }
    return arr;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值