归并排序
归并排序(MERGE-SORT)是建立在归并操作上的一种有效的排序算法,该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为二路归并。
算法思想:递归
1、一分为二,再对排好序的俩数组进行合并。
2、递归结束条件:要归并的数组的长度为1时,返回该数组
function merge(left, right) {
var tmp = [];
while (left.length && right.length) {
if (left[0] < right[0])
tmp.push(left.shift());
else
tmp.push(right.shift());
}
return tmp.concat(left, right);//**无论谁剩余均并入即可
}
function mergeSort(arr) {
if (arr.length === 1)
return a;
var mid = (arr.length / 2)
, left = arr.slice(0, mid)
, right = arr.slice(mid);
return merge(mergeSort(left), mergeSort(right));
}
var arr1 = [3, 5, 2,2,4, 8, 6];
console.log(mergeSort(arr1)); //[2,2, 3, 4, 5, 6, 8 ]
基数排序
基数排序(radix sort)属于“分配式排序”(distribution sort),又称“桶子法”(bucket sort)或bin sort,顾名思义,它是透过键值的部份资讯,将要排序的元素分配至某些“桶”中,藉以达到排序的作用,基数排序法是属于稳定性的排序,其时间复杂度为O (nlog®m),其中r为所采取的基数,而m为堆数,在某些时候,基数排序法的效率高于其它的稳定性排序法。
应用:多关键字排序(低位优先与高位优先)
function RadixLSDSort(arr, digit) {
const radix = 10; // 基数,以10进制来进行排序
var i = 0,
j = 0,
count = Array(radix), // 0~9的桶
len = arr.length,
bucket = Array(len);
// 利用LSD,也就是次位优先
for (var d = 0; d < digit; d++) {
//初始化
for (i = 0; i < radix; i++) {
count[i] = 0;
}
// 向各个桶中添加元素,并统计出每个桶中装的个数
for (i = 0; i < len; i++) {
j = getDigit(arr[i], d);
count[j]++;
}
// count的越往后值最大,最大值为arr.length
// count数组的值为,该位数值为该索引的数字总数
for (i = 1; i < radix; i++) {
count[i] = count[i] + count[i - 1];
}
// 按照桶的顺序将导入temp中
for (i = len - 1; i >= 0; i--) {
j = getDigit(arr[i], d);
bucket[count[j] - 1] = arr[i];
count[j]--;
}
// 将已经根据相应位数排好的序列导回arr中
for (i = 0; i < len; i++) {
arr[i] = bucket[i];
}
}
return arr
}
// 获得每位的数字
function getDigit(x, d) {
var a = [1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000];
return (Math.floor(x / a[d]) % 10); //Math.floor向下取整
}
var arr1 = [3, 5, 2, 2, 4, 8, 6];
console.log(RadixLSDSort(arr1)); //[ 2, 3, 4, 5, 6, 8 ]
//方式2
var counter = [];
// 定义一个函数 arr待排序数组 maxDigit数组中最大数的位数,例如[1,10,100]的maxDigit为3
function radixSort(arr, maxDigit) {
var mod = 10;
var dev = 1;
for (var i = 0; i < maxDigit; i++, dev *= 10, mod *= 10) {
// 把待排序的数组 arr 中的每一位整数,插入对应的容器
for(var j = 0; j < arr.length; j++) {
// 从个位开始,得到数组中每个数的每一位并保存在 bucket 变量中
// bucket 变量的值可能为 0 1 2 3 4 5 6 7 8 9
// 与之对应的 counter[bucket] 容器为 0 1 2 3 4 5 6 7 8 9
var bucket = parseInt((arr[j] % mod) / dev);
// 如果目前 bucket 变量的值对应的 counter[bucket] 容器还不存在(未初始化),则创建(初始化)一个新的空容器
if(counter[bucket]==null) {
counter[bucket] = [];
}
// 现在把这个 bucket 变量的值插入对应的 counter[bucket] 容器的尾部
counter[bucket].push(arr[j]);
}
// 把 counter[bucket] 容器里的数依次取出
var pos = 0;
for(var j = 0; j < counter.length; j++) {
// 定义一个变量 value 用于保存conter[j].shift
var value = null;
if(counter[j]!=null) {
while ((value = counter[j].shift()) != null) {
arr[pos++] = value;
}
}
}
}
return arr;
}
console.log(radixSort([99,15,48,75,46,37,90,100],3));