八大排序算法-其他排序(归并排序、基数排序)

八大排序算法-其他排序(归并排序、基数排序)

归并排序

归并排序(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));


猜你喜欢

转载自blog.csdn.net/qq_40151857/article/details/82831152