JavaScript 数据结构与算法十大经典排序算法-插入排序(二)

插入排序分为 直接插入排序 和优化后的 折半插入排序希尔排序,通常所说的是直接插入排序。

一、直接插入

原理

通过构建有序序列,对于未排序的数据,在已排序序列中从后向前扫描,找到相应位置并插入。

步骤

  1. 从第一个元素开始,该元素认为是已经被排过序的
  2. 取出下一个元素,在已排序的元素序列中从后向前做对比
  3. 如果对比的元素(已排序)大于新元素,将该元素移到下一个位置,也就是往后移一位
  4. 重复步骤 3 ,直到找到已排序的元素小于或者等于新元素的位置
  5. 将新元素插入到该位置
  6. 重复步骤2 ~ 5

实现

// 插入排序
const insertSort = array => {
	let len = array.length
	if (len<1) return
	let preIndex, current;
	for (let i = 1; i<len; i++){
		preIndex = i - 1 // 待比较元素的标
		current = array[i] //当前元素
		while (preIndex >= 0 && array[preIndex] > current){
			array[preIndex+1] = array[preIndex] //将待比较元素后移一位
			preIndex -- //游标前移一位
		}
		if (preIndex + 1 != i){
			//避免同一个元素赋值给自身
			array[preIndex + 1] = current //将当前元素插入预留空位
		}
	}
	return array
}

在这里插入图片描述

二、折半插入

原理

折半插入排序是直接插入排序的升级版,鉴于插入排序第一部分为已排好序的数组,我们不必按顺序依次寻找插入点,只需要比较他们的中间值与带插入元素的大小即可。

步骤

  1. 取0 ~ i-1 的中间点( m = (i-1) >> 1,有符号右移运算,等于 Math.floor((i-1)/2 ),array[i] 与 array[m] 进行比较,若 array[i] > array[m],则说明待插入的元素在 m ~ i-1 索引之间,反之在0 ~ m 之间。
  2. 重复步骤 1,每次缩小一半的查找范围,直至找到插入的位置
  3. 将数组中插入位置之后的元素全都后移一位
  4. 在指定位置插入第 i 个元素(即待插入的元素)。

注:x >> 1 是位运算中的右移运算,表示右移一位,等同于 x 除以 2 再取整,即 x >> 1 == Math.floor(x/2) 。 x<<1等于x*2

// 这般插入排序
cosnt binaryInsertSort = array => {
	const len = array.length;
	if (len <= 1) return;

	let current, i, j, low, high, m;
	for (i = 1; i < len; i++) {
		low = 0;
		high = i - 1;
		current = array[i];

		while (low <= high) {
			//步骤 1 & 2 : 折半查找
			m = (low + high) >> 1; // 注: x>>1 是位运算中的右移运算, 表示右移一位, 等同于 x 除以 2 再取整, 即 x>>1 == Math.floor(x/2) .
			if (array[i] >= array[m]) {
				//值相同时, 切换到高半区,保证稳定性
				low = m + 1; //插入点在高半区
			} else {
				high = m - 1; //插入点在低半区
			}
		}
		for (j = i; j > low; j--) {
			//步骤 3: 插入位置之后的元素全部后移一位
			array[j] = array[j - 1];
			console.log('array2 :', JSON.parse(JSON.stringify(array)));
		}
		array[low] = current; //步骤 4: 插入该元素
	}
	console.log('array2 :', JSON.parse(JSON.stringify(array)));
	return array;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值