今天室友面了一下B站,没想到昨天正准备梳理一下所有的排序方法呢,没想到今天他面试又考了一道快速排序。所以说,这个排序还是很重要的啊。废话不多说,还是接着昨天剩下的,今天就再来梳理梳理其他的排序方法吧!
快速排序
快速排序的原理就是选择一个基准值,然后把比它小的放一边,把比它大的再放一边,然后在分开重复上面的操作。面试官今天问我室友这个原理的时候,他说是二分的思想,不知道大家赞同不赞同!
还是昨天那个例子:
原数组 [5,1,3,6,2,8,3]
取最左边为5,为基准值
第一次左边 [1,3,2,3] 右边[6,8]
再递归分别对左右两边的数组进行排序,一样的程序 最后合并数组
具体的代码实现就是:
function quickSort(arr){
if(arr.length<2){
return arr
}
let pivot = arr[0]
let left = []
let right = []
for(let i=1; i<arr.length; i++){
if(arr[i]<=pivot){
left.push(arr[i])
}else{
right.push(arr[i])
}
}
return quickSort(left).concat([pivot]).concat(quickSort(right))
}
这种方法需要开辟新的数组,有点消耗空间。还有一种方法不需要单独的开辟数组来存储:
function quickSort(arr, left, right) {
if (left >= right) return; // 终止条件:子数组长度为 0 或 1
const pivot = arr[right]; // 选择最后一个元素作为基准值
let j = left; // 指针 j 指向小于基准值的最后一个元素的位置
for (let i = left; i < right; i++) {
if (arr[i] < pivot) {
// 交换 arr[i] 和 arr[j]
[arr[i], arr[j]] = [arr[j], arr[i]];
j++;
}
}
// 将基准值放到正确的位置
[arr[right], arr[j]] = [arr[j], arr[right]];
// 递归排序左右两部分
quickSort(arr, left, j - 1);
quickSort(arr, j + 1, right);
}
这样就在一个数组里面完成了。
但是在现在内存大的可怜的情况下,我更喜欢用第一种当时,还是很简单,很容易懂的。我看还有大佬直接用数组的filter方法,过滤出比基准值大的和小的。那代码数太少了,看着很舒服,但是如果可以用那个数组的那些方法的话,直接用sort不是更好,害。
插入排序
插入排序就是将一个乱的数插入到前面顺序对的部分的合适的位置。这个就比较简单了,就不做例子演示了,直接编写代码吧。
代码示例:
function insertSort(arr){
let preIndex,current
for(let i = 1;i<arr.length;i++){
preIndex = i-1
current = arr[i]
while(preIndex>=0 && arr[preIndex]>current){
arr[preIndex+1] = arr[preIndex]
preIndex--
}
arr[preIndex+1] = current
}
}
这里就是定义一个前面的下标,和一个当前需要排序的值。如果前面的值比当前的值大的话就代表这个顺序是乱的,就依次将前面的值往后推一个位子,直到不比当前的值大为止。
希尔排序
希尔排序其实就是插入排序的一个改进版,先对数组进行分组,一般是数组长度的一半进行间隔分组,然后对这个小分组进行插入排序,再取一半的一半进行分组,在进行插入排序,直到分组间隔变成1之后,成为一个大数组,排完序即可。这里我就先不写了,有兴趣的可以自己了解下,我我我,暂时没有兴趣。感谢大佬
总结
通过几次面试来看,面试考察到排序这方面的知识还是很频繁的,所以还是要好好看看排序哦。害,怪就只怪当时数据结构课没有好好听,现在要好一顿捋了。加油哦,你很棒。