Go版数据结构 -【8.1 冒泡排序】

8.1 冒泡排序

冒泡排序是一种简单且直观的排序算法。它的基本思想是通过多次遍历待排序的序列。

每次比较相邻的两个元素,如果它们的顺序不正确(例如,第一个比第二个大),就交换它们的位置。

经过多次这样的操作,较大的元素会逐渐冒泡到序列的末端。

本节代码存放目录为 lesson16

概念与原理

冒泡排序的原理如下:

  • 从序列的起始位置开始,逐对比较相邻的元素。

  • 如果第一个元素比第二个大,就交换它们。

  • 继续比较相邻元素,直到序列末尾,最大值会被冒泡到序列的末端。

  • 重复步骤 1-3,直到整个序列有序。

冒泡排序是一种稳定的排序算法,即当两个元素相等时,它们的顺序不会改变。

冒泡排序的步骤示例

给定如下无序数组,按照从小到大排序:

[5, 3, 8, 4, 2]

通过冒泡排序的步骤如下:

第一轮:

比较 arr[0] 与 arr[1],5 与 3 比较,交换:[5, 3, 8, 4, 2] -> [3, 5, 8, 4, 2]

比较 arr[1] 与 arr[2],5 与 8 比较,不交换:[3, 5, 8, 4, 2] -> [3, 5, 8, 4, 2]

比较 arr[2] 与 arr[3],8 与 4 比较,交换:[3, 5, 8, 4, 2] -> [3, 5, 4, 8, 2]

比较 arr[3] 与 arr[4],8 与 2 比较,交换:[3, 5, 4, 8, 2] -> [3, 5, 4, 2, 8]

经过第一轮,最大的一个数组已经被移动到了最后的位置,也就是:8 目前在最后一位了。

第二轮:

比较 arr[0] 与 arr[1],3 与 5 比较,不交换:[3, 5, 4, 2, 8] -> [3, 5, 4, 2, 8]

比较 arr[1] 与 arr[2],5 与 4 比较,交换:[3, 5, 4, 2, 8] -> [3, 4, 5, 2, 8]

比较 arr[2] 与 arr[3],5 与 2 比较,交换:[3, 4, 5, 2, 8] -> [3, 4, 2, 5, 8]

经过第二轮,后面两位都已经排列好了。

第三轮:

比较 arr[0] 与 arr[1],3 与 4 比较,不交换:[3, 4, 2, 5, 8] -> [3, 4, 2, 5, 8]

比较 arr[1] 与 arr[2],4 与 2 比较,交换:[3, 2, 4, 5, 8] -> [3, 2, 4, 5, 8]

经过第三轮,后面三位都已经排列好了。

第四轮:

比较 arr[0] 与 arr[1],3 与 2 比较,交换:[3, 2, 4, 5, 8] -> [2, 3, 4, 5, 8]

至此,冒泡排序已经完成,经过四轮冒泡,10 次比较最终得出了结果。

总的来说,冒泡排序就是经过 n - 1轮,从 arr[0] 一直到 arr[n -1] 进行逐个比较,最后将数组都按照序列规则排列。


冒泡排序的时间复杂度如下所示:

  • 最坏情况O(n²),即数组本身是反序排列的。

  • 最好情况O(n),即数组已经是有序的。

  • 平均情况O(n²),即数组是随机排列的。

冒泡排序时间复杂度较高,但它简单易懂,比较适合用于我们的学习理解。

Go语言的实现

接下来我们使用 Go 语言实现一个冒泡排序算法:

func bubbleSort(arr []int) {
	length := len(arr)
	num := 0

	// 轮次控制
	for i := 0; i < length-1; i++ {
		fmt.Printf("\n第 %d 轮\n", i+1)

		// 比较次数控制
		for j := 0; j < length-i-1; j++ {
			num++
			if arr[j] > arr[j+1] {
				arr[j], arr[j+1] = arr[j+1], arr[j]
			}
			fmt.Printf("第 %d 次比较,结果: %v\n", num, arr)
		}
	}
}

func main() {
	arr := []int{5, 3, 8, 4, 2}
	bubbleSort(arr)
	fmt.Println("排序结果: ", arr)
}

执行结果如下所示:

1 轮
第 1 次比较,结果: [3 5 8 4 2]2 次比较,结果: [3 5 8 4 2]3 次比较,结果: [3 5 4 8 2]4 次比较,结果: [3 5 4 2 8]2 轮
第 5 次比较,结果: [3 5 4 2 8]6 次比较,结果: [3 4 5 2 8]7 次比较,结果: [3 4 2 5 8]3 轮
第 8 次比较,结果: [3 4 2 5 8]9 次比较,结果: [3 2 4 5 8]4 轮
第 10 次比较,结果: [2 3 4 5 8]
排序结果:  [2 3 4 5 8]

代码优化

冒泡排序可以通过提前判断是否已经有序来优化。如果在一轮排序过程中没有发生任何交换操作,说明数组已经是有序的,可以提前结束排序。

如下代码所示:

func bubbleSortOpm(arr []int) {
	length := len(arr)
	num := 0

	// 轮次控制
	for i := 0; i < length-1; i++ {
		fmt.Printf("\n第 %d 轮\n", i+1)

		// 此次是否进行过交换
		swapped := false

		// 比较次数控制
		for j := 0; j < length-i-1; j++ {
			num++
			if arr[j] > arr[j+1] {
				swapped = true
				arr[j], arr[j+1] = arr[j+1], arr[j]
			}
			fmt.Printf("第 %d 次比较,结果: %v\n", num, arr)
		}

		// 如果没有发生交换,说明数组已经有序,提前退出
		if !swapped {
			break
		}
	}
}

在上面的代码中,我们增加了 swapped 参数,当前轮次元素顺序没有更新时,那么说明已经排序好了,就没有必要再往下走了。

小结

本节我们讲解了冒泡排序的基本原理、步骤示例和 Go 语言的实现。

关于本节总结如下:

  • 时间复杂度:最坏情况下为 O(n²),最好情况下为 O(n)

  • 稳定性:冒泡排序是稳定的排序算法。

  • 应用场景:由于其简单性,冒泡排序主要用于学习和小型数据集的排序,不适用于大型数据集的排序。


我的GitHub:https://github.com/swxctx

书籍地址:https://gs.golang.website/

书籍代码:https://github.com/YouCanGolang/GoStructedCode

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Swxctx

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

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

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

打赏作者

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

抵扣说明:

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

余额充值