炫酷的js十大排序算法(下)

堆排序

堆排序算法是一种基于堆数据结构的排序算法,其核心思路在于将待排序数组看做二叉树,通过构建大顶堆或小顶堆来实现排序。对于大顶堆,每个节点的值均大于或等于它的子节点;对于小顶堆,每个节点的值均小于或等于它的子节点。排序时,取堆顶元素,将其存储到已排序数组中,并从堆中删除;然后重新调整剩余元素形成新的堆,重复以上操作直至所有元素排序完成

代码 

var len1; // 因为声明的多个函数都需要数据长度,所以把len设置成为全局变量
 
function buildMaxHeap(arr) {
  // 建立大顶堆
  len1 = arr.length;
  for (var i = Math.floor(len1 / 2); i >= 0; i--) {
    heapify(arr, i);
  }
}
 
function heapify(arr, i) {
  // 堆调整
  var left = 2 * i + 1,
    right = 2 * i + 2,
    largest = i;
 
  if (left < len && arr[left] > arr[largest]) {
    largest = left;
  }
 
  if (right < len && arr[right] > arr[largest]) {
    largest = right;
  }
 
  if (largest != i) {
    swap(arr, i, largest);
    heapify(arr, 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--;
    heapify(arr, 0);
  }
  return arr;
}
 
let arr = [3, 44, 38, 5, 47, 15, 36, 26, 27, 12, 46, 4, 19, 50, 48];
 
console.log(heapSort(arr)); // [3,  4,  5, 12, 15, 19, 26, 27, 36, 38, 44, 46, 47, 48, 50]

计数排序

计数排序(Counting Sort)是一种非基于比较的排序算法,其时间复杂度为O(n+k),其中k表示待排序数组中最大元素与最小元素之差加1。该算法的基本思想是统计每个元素在待排序数组中出现的次数,然后根据统计结果构建有序序列。

代码 

function countingSort(arr, maxValue) {
  var bucket = newArray(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;
}

插入排序 

1、第一个元素默认已排好序,从第二个元素开始。
2、如果第二个元素比第一个元素小,那就交换二者位置,否则不交换,前两个元素的顺序已经固定。
3、第三个元素与前两个元素进行比较,从后向前比,先与第二个元素比,如果比第二个元素小,再与第一个元素比,比第一个元素小,就放在第一个元素的位置,第一个元素和第二个元素向后移一个位置;如果第三个元素不比第二个元素小,不交换位置,这趟的排序以固定,也就是前三个元素的大小顺序已经排好。
4、之后的排序也是这么进行。


 

代码 

function insertSort(arr) {
  var len1 = arr.length;
  for (var i = 1; i < len1; i++) {
    var now = arr[i]; // 当前趟的元素
    var lastIndex = i - 1; // 已经排好序的序列里的最后一个元素
    // 从后向前遍历已经排好序的序列
    // 如果当前趟的元素now比已经排好序的序列的元素小
    while (lastIndex >= 0 && arr[lastIndex] > now) {
      arr[lastIndex + 1] = arr[lastIndex]; // 将比now大的元素向后移一个位置
      lastIndex--;
    }
    arr[lastIndex + 1] = now; // 将当前趟的元素now插入到已经排好序的序列里
  }
  return arr;
}
 
var arr = [3, 44, 38, 5, 47, 15, 36, 26, 27, 12, 46, 4, 19, 50, 48];
 
console.log(insertSort(arr)); // [3,  4,  5, 12, 15, 19, 26, 27, 36, 38, 44, 46, 47, 48, 50]

桶排序 

桶排序(Bucket Sort)是一种线性排序算法,它利用了函数的映射关系,将要排序的数据分到有限数量的桶子里,每个桶子再分别排序。桶排序的时间复杂度取决于桶的数量和桶内使用的排序算法,通常情况下是O(n+k)。

代码 

function bucketSort(arr, bucketSize) {
  if (arr.length === 0) {
    return arr;
  }
 
  var minValue = arr[0];
  var maxValue = arr[0];
  for (var i = 1; i < arr.length; i++) {
    if (arr[i] < minValue) {
      minValue = arr[i]; // 输入数据的最小值
    } else if (arr[i] > maxValue) {
      maxValue = arr[i]; // 输入数据的最大值
    }
  }
 
  // 桶的初始化
  var DEFAULT_BUCKET_SIZE = 5; // 设置桶的默认数量为5
  bucketSize = bucketSize || DEFAULT_BUCKET_SIZE;
  var bucketCount = Math.floor((maxValue - minValue) / bucketSize) + 1;
  var buckets = newArray(bucketCount);
  for (var i = 0; i < buckets.length; i++) {
    buckets[i] = [];
  }
 
  // 利用映射函数将数据分配到各个桶中
  for (var i = 0; i < arr.length; i++) {
    buckets[Math.floor((arr[i] - minValue) / bucketSize)].push(arr[i]);
  }
 
  arr.length = 0;
  for (var i = 0; i < buckets.length; i++) {
    insertionSort(buckets[i]); // 对每个桶进行排序,这里使用了插入排序
    for (var j = 0; j < buckets[i].length; j++) {
      arr.push(buckets[i][j]);
    }
  }
 
  return arr;
}

基数排序

基数排序(Radix Sort)是一种多关键字排序算法,可用于对数字序列进行排序。基数排序先按照最低有效位(LSB)对元素进行排序,然后依次按照次低有效位、次次低有效位……最高有效位进行排序。该算法的时间复杂度为O(d*(n+k)),其中d表示数字位数,k表示每个数字可能的取值范围。

代码 

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

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值