归并排序
将每个元素拆分成大小为1的分区
递归地合并相邻的分区
遍历 i = 左侧首项位置 到 右侧末项位置
如果左侧首项的值 <= 右侧首项的值
拷贝左侧首项的值
否则: 拷贝右侧首项的值; 增加逆序数
将元素拷贝进原来的数组中
代码实现
let mergeSort = arr =>{
let k = arr.length
if(k===1){return arr} //数组长度为一,即默认每个数自己是排好队的
//把数组分为左边和右边两个数组
let left = arr.slice(0, Math.floor(k/2)) //左
let right = arr.slice(Math.floor(k/2)) //右
return merge(
//把右边的数组和右边的数组再进行mergeSort操作(分左右,直到每个数
mergeSort(left), mergeSort(right)组内只有一个元素)
)
}
//下面这个部分,语言很难表述清楚,是数组合并的过程
let merge = (a, b) => {
if(a.length === 0) return b
if(b.length === 0) return a
return a[0] > b[0] ?
[b[0]].concat(merge(a, b.slice(1))) :
[a[0]].concat(merge(a.slice(1), b))
}
merge过程示意图
计数排序
创建关键值(计数)数组
遍历数列中的每个元素
相应的计数器增加 1
每轮计数,都从最小的值开始
当计数为非零数时
重新将元素存储于列表
将计数减1
代码实现
let countSort = arr =>{
let hashTable = {}, max = 0, result = [] //假设这个数组中最大的数是0,用来存放排列好的数组是result
// 遍历数组
for(let i=0; i<arr.length; i++){
if(!(arr[i] in hashTable)){
hashTable[arr[i]] = 1
}else{
hashTable[arr[i]] += 1
}
if(arr[i] > max) {max = arr[i]}
}
// 遍历哈希表
for(let j=0; j<=max; j++){
if(j in hashTable){
//如果相同的数字出现多次,出现几次push这个数几次
for(let i = 0; i<hashTable[j]; i++){
result.push(j)
}
}
}
return result
}
其他排序
此外还有冒泡排序,插入排序,希尔排序,基数排序(基数排序比较适合多位数排序,即每个数字都很大,有好几位数字)。