关于排序
- 总共讲解七种排序
- 选择排序
- 快速排序
- 归并排序
- 计数排序
- 冒泡排序
- 插入排序
- 所有的递归都可以写成循环。所以每种排序都有递归写法和循环写法。
选择排序
参考博客:算法入门 【上】
快速排序
递归思路——以x为基准,比他小的排到他前面,比他大的排到他后面。
这样x位置就永远定下来了!因为他前面的全是比他小的,后面全是比他大的。那前面那些数字自己在排序,后面的也自己在排序。x就永远不动了!
那左边和右边的数组也像这样选个基准排序。
代码(阮一峰版本)
快速排序
quickSort = arr => { //接收一个数组
let if (arr.length <= 1) { return arr; } //如果这个数组小于等于1,就直接返回这个数组
let pivotIndex = Math.floor(arr.length / 2); // 把数组中最中间(或中间偏左)的那个元素作为基准
let pivot = arr.splice(pivotIndex, 1)[0]; //把这个基准的人单独拎出来(在基准的下标处删除一个,得到一个数组)
let left = []; // 生成一个left的数组
let right = []; //生成一个right数组
for (let i = 0; i < arr.length; i++){ //遍历删掉基准后的arry,比基准元素小的就放到left,比基准元素大的就放到right
if (arr[i] < pivot) { left.push(arr[i])
} else { right.push(arr[i]) }
}
return quickSort(left).concat(
[pivot], quickSort(right) )
} //最后返回一个数组,这个数组:对left快排得到的数组+基准元素+对right快排得到的数组
归并排序(merge)
- 把两个排好序的数组合并merge成一个新的排好序的数组。
- 把一个数组分为左右两边数组
- 所以把一个数组一直分左右两个数组,再分左右两个数组,直到变成一个元素组成的数组。好啦,就可以开始合并了。把一个元素的数组和另一个一个元素的数组合并,在和其他合并合并合并完事
- 图解
代码
let mergeSort = arr =>{ 接受一个数组
if(arr.length===1){return arr} 如果你的长度是1 ,默认排好序(精髓)
let left = arr.slice(0, Math.floor(arr.length/2)) 左半部分
let right = arr.slice(Math.floor(arr.length/2)) 右半部分
return merge(mergeSort(left), mergeSort(right)) 左边用算法排好序,右边用算法排好序,合并
}
let merge = (a, b) => { merge接收两个数组,a和b
if(a.length === 0) return b 如果a空了,返回B
if(b.length === 0) return a 如果b空了,返回a
return a[0] > b[0] ? 如果都没有空,就找到两个数组中,谁的第一个最小,如果b 0的第一个最小
[b[0]].concat(merge(a, b.slice(1))) : 那我就用b0连接上a和b的其他部分的merge
[a[0]].concat(merge(a.slice(1), b))
}
计数排序
思路:
- 用一个哈希表做记录
- 发现数字N就记N:,如果再次发现N就加1
- 最后把哈希表的ke全部打出来,假设N:m,那么N就需要打印M次
代码
let countSort = arr => {
let hashTable = {}, max = 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++) { //遍历0到最大数,看哈希表里面有没有这个key
if (j in hashTable) {
for (let i = 0; i < hashTable[j]; i++) {
result.push(j);
}
}
}
return result;
};
计数排序的特点
- 使用了额外的hashTable
- 只便利数组一遍(不过还要遍历一次hashTable)
- 这叫做 [ 用空间换时间 ]
时间复杂度对比
- 选择排序O(n^2)
- 快速排序O(n log2 n)
- 归并排序O(n log2 n)
- 计数排序O(n + max) 时间快但同时内存也多了
冒泡排序
插入排序
visualgo.net/zh/sorting 点击INS
希尔排序
sorting.at/ 自己选择Shell Sort
基数排序
visualgo.net/zh/sorting 点击RAD
算法学习总结
战略上藐视敌人,战术上重视敌人
特点
- 思路都很简单
- 细节都很多
- 多画表,多画图,多log
- 如果实在不想陷入JS的细节,可以用伪代码