Go 实现插入排序算法及优化

Go 实现插入排序算法及优化

耐心和持久胜过激烈和狂热。

哈喽大家好,我是陈明勇,今天分享的内容是使用 Go 实现插入排序算法。如果本文对你有帮助,不妨点个赞,如果你是 Go 语言初学者,不妨点个关注,一起成长一起进步,如果本文有错误的地方,欢迎指出!

插入排序

插入排序是一种简单的排序算法,以数组为例,我们可以把数组看成是多个数组组成。插入排序的基本思想是往前面已排好序的数组中插入一个元素,组成一个新的数组,此数组依然有序。光看文字可能不理解,让我们看看图示:

在这里插入图片描述
插入排序的时间复杂度为 O(N²)。

算法实现

import (
	"fmt"
)

func main() {
	nums := [4]int{4, 1, 3, 2}
	fmt.Println("原数组:", nums)
	fmt.Println("--------------------------------")
	InsertionSort(nums)
}

func InsertionSort(nums [4]int) {
	for i := 1; i < len(nums); i++ {
		for j := i; j > 0 && nums[j] < nums[j-1]; j-- {
			nums[j], nums[j-1] = nums[j-1], nums[j]
		}
		fmt.Printf("第 %d 轮后:%v\n", i, nums)
	}
	fmt.Println("--------------------------------")
	fmt.Println("排序后的数组:", nums)
}

执行结果:

原数组: [4 1 3 2]
--------------------------------
第 1 轮后:[1 4 3 2]
第 2 轮后:[1 3 4 2]
第 3 轮后:[1 2 3 4]
--------------------------------
排序后的数组: [1 2 3 4]
  • 第一层循环的 i 变量,表示待排序的元素;
  • 第二层循环:
    • j 变量的初值为 i 的值,由 j 变量往前去寻找待插入的位置;
    • 循环条件为 j > 0 && nums[j] < nums[j - 1]
      • j > 0 → 寻找到左边界则结束寻找;
      • nums[j] < nums[j - 1] → 左边元素小于待排序的元素则结束寻找;
    • 循环体为元素交换逻辑,只要满足循环条件,则不断交换元素,直到交换到待插入的位置,才终止。

算法优化

上面的代码,是通过不断地交换元素,直到无法交换,才能将元素放置到待插入的位置,为了避免频繁交换元素而导致效率低,将交换的逻辑变成把前面的数往后移,最后再将待排序的元素插入到合适的位置即可。

import (
	"fmt"
)

func main() {
	nums := [4]int{4, 1, 3, 2}
	fmt.Println("原数组:", nums)
	fmt.Println("--------------------------------")
	InsertionSort(nums)
}

func InsertionSort(nums [4]int) {
	for i := 1; i < len(nums); i++ {
		t := nums[i]
		j := i
		for ; j > 0 && t < nums[j-1]; j-- {
			nums[j] = nums[j-1]
		}
		nums[j] = t
		fmt.Printf("第 %d 轮后:%v\n", i, nums)
	}
	fmt.Println("--------------------------------")
	fmt.Println("排序后的数组:", nums)
}
  • 用变量 t 记录待排序的元素,用 j 变量往前查找,只要前面的数比 t 大,那么就往后移,最后将 t 插入到合适的位置。

小结

  • 本文首先对插入排序进行简单地介绍,通过图片来演示插入排序的过程,然后使用 Go 语言实现插入排序的算法。为减少算法中交换次数的逻辑,对算法进行优化,将交换的逻辑变成把前面的数往后移,最后将待排序的数插入到合适的位置即可。
  • 除了这种优化方式,还有一种改造方式:普通的算法往左查找的方式是线性查找,由于元素是有序的,因此线性查找可以换成二分查找,但是经过二分找到待插入的位置之后,也得移动前面的元素,相比上面的优化方法,还多了 O(logn) 的查找时间复杂度,因此我认为没有必要改造成二分查找。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序员陈_明勇

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值