javascript算法系列——排序4:插入排序与快速排序

一: 插入排序

插入排序与之前学习过的冒泡排序(循环n趟,每趟与所有的数字进行比较,大就交换位置),选择排序(循环n趟,每趟对比(n-i)个数字,找出最小的,将其与i的位置的数字互换)并称为low B三人组哈哈哈,为啥low呢,自然是时间复杂度不够完美~

插入排序的核心思想:
类比斗地主吧。每次将从无序区摸出的牌与手里的牌进行对比,放到正确的位置。
在这里插入图片描述
循环n趟,从后往前一次对比,每个数对比i-1次,记录当前的数,如果前面的数比自己大,就将大的数依次往后移,直到移完或者下一个数不再比自己大位置,将自己插入到该位置。
在这里插入图片描述
javascript代码:

const insertSort = (arr) => {
    for (let i = 1; i <arr.length; i++) {
        const temp = arr[i]
        let j = i - 1
        while(j >= 0 && temp < arr[j]) {
            arr[j+1] = arr[j] 
            j--
        }
        arr[j+1] = temp
    }
    return arr
}
console.log(insertSort(arr))

关键点:从第二张牌开始!j是指针,其实位置为当前位置-1

python代码:

def insert_sort(li):
	for i in range(1,len(li)):
	 	tmp = li[i]
	 	j = i - 1
	 	while j>=0 and li[j] > tmp:
	 		li[j+1] = li[j]
	 		j-=1
	 	li[j+1] = tmp
	return li
二:快速排序

快速排序,能叫这个名字那必然是足够快。
核心思想:递归!!先将一个区间内的元素放到他该在的位置,然后将数据分成左右两个区间,再对区间内的元素递归该过程。
请添加图片描述
先写伪代码:
假设我们使元素归位的函数叫:partition,那么快速排序伪代码就是:

const quick_sort = (arr, left, right) => {
	let mid = null;
	if (left < right) {
		mid = partition(arr, left, right);
		quick_sort(arr, left, mid - 1);
		quick_sort(arr, mid + 1, right);
	}
}

关键点在于如何将指定区间内的元素归位,也就是partition这个函数咋实现
partition的核心思想:
left, right两个指针,left指向要归位元素的位置,right在区间最后,把要归位的元素暂存起来,左边有个空位,左边是给比该元素小的数的,从右找第一个比该元素小的数,移过去,这时候右边有个空位,右边是给比该元素大的数的,再从左边找第一个比该元素大的数,移过去,当left和right相等的时候,就是该元素的空位。将该元素放到这个位置即可。

代码实现:

const partition = (arr, left, right) => {
	let tmp = arr[left]
	while (left < right) {
		while (left < right && arr[right] >= tmp) {
			right--
		}
		arr[left] = arr[right]
		while (left < right && arr[left] <= tmp) {
			left++
		}
		arr[right] = arr[left]
	}
	arr[left] = tmp
	return left
}
2.1:快速排序的缺点
  • 最坏情况
  • 递归最大深度

一般语言都会有最大递归深度,比如python理论上的最大递归深度是997,虽然可以手动更改最大递归深度,但是递归还是个比较耗内存的操作,这个无法避免。以空间换时间。

最坏情况:一个完全逆序的数组比如 [9,8,7,6,5,4,3,2,1]
这样相当于每次left和right区间只减少了1个数字,其效率与lowB三人组的效率相差不大。
解决办法:随机取一个数与第一位数进行交换,再快排。无法完全避免,但可以大大减少最坏情况出现的概率。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值