0
点赞
收藏
分享

微信扫一扫

冒泡排序(bubbleSort)

静鸡鸡的JC 2022-03-11 阅读 32

算法思路:
从第一个元素开始,两两比较相邻两个元素数值的大小,数值大的放在后面(从小到大排列)
平均时间复杂度:O(n2)
最差时间复杂度:O(n2)
最佳时间复杂度:O(n)
空间复杂度:O(1)
稳定性:不稳定
适合场景:少量元素

代码实现:
方式一:双层循环遍历
i : 当前正在排序的索引左边界
j:用来遍历数组,进行冒泡操作

package main

import "fmt"

func main() {
	arr := []int{1, 7, 6, 7, 98, 9, -1, 7, 89, 14, -4, -5, -657}
	bubbleSort(arr)
	for _, v := range arr {
		fmt.Println(v)
	}
}

func bubbleSort(arr []int) {
	for i := 0; i < len(arr)-1; i++ {
		for j := 0; j < len(arr)-1; j++ {
			if arr[j] > arr[j+1] {
				swap(arr, j, j+1)
			}
		}
	}
}

func swap(arr []int, i, j int) {
	tem := arr[i]
	arr[i] = arr[j]
	arr[j] = tem
}

时间复杂度:O(n2)
数据交换次数:(n - 1) * (n - 1) =(n - 1)2
总复杂度:(n - 1)2

方式二:减少比较次数
代码一:
i : 已排好序的序列的个数
j:用来遍历数组,进行冒泡操作

package main

import "fmt"

func main() {
	arr := []int{1, 7, 6, 7, 98, 9, -1, 7, 89, 14, -4, -5, -657}
	bubbleSort(arr)
	for _, v := range arr {
		fmt.Println(v)
	}
}

func bubbleSort(arr []int) {
	for i := 0; i < len(arr)-1; i++ {
		for j := 0; j < len(arr)-1-i; j++ {
			if arr[j] > arr[j+1] {
				swap(arr, j, j+1)
			}
		}
	}
}

func swap(arr []int, i, j int) {
	tem := arr[i]
	arr[i] = arr[j]
	arr[j] = tem
}

代码二:
i : 已排好序的序列的左边界索引
j:用来遍历数组,进行冒泡操作

package main

import "fmt"

func main() {
	arr := []int{1, 7, 6, 7, 98, 9, -1, 7, 89, 14, -4, -5, -657}
	bubbleSort(arr)
	for _, v := range arr {
		fmt.Println(v)
	}
}

func bubbleSort(arr []int) {
	for i := len(arr) - 1; i > 0; i-- {
		for j := 0; j < i; j++ {
			if arr[j] > arr[j+1] {
				swap(arr, j, j+1)
			}
		}
	}
}

func swap(arr []int, i, j int) {
	tem := arr[i]
	arr[i] = arr[j]
	arr[j] = tem
}

时间复杂度:O(n2)
数据交换次数:(n - 1) + (n - 2) + (n - 3)+ ……+ 1 = 1/2n2 - 1/2n
总复杂度:1/2n2 - 1/2n

方式三:外循环优化
如果在某次的比较过程中,发现没有任何元素移动,则不再进行接下来的比较,证明已经排好序。
i : 已排好序的序列的左边界索引
j:用来遍历数组,进行冒泡操作
flag:判断数组是否已经有序

package main

import "fmt"

func main() {
	arr := []int{1, 7, 6, 7, 98, 9, -1, 7, 89, 14, -4, -5, -657}
	bubbleSort(arr)
	for _, v := range arr {
		fmt.Println(v)
	}
}

func bubbleSort(arr []int) {
	for i := len(arr) - 1; i > 0; i-- {
		flag := false
		for j := 0; j < i; j++ {
			if arr[j] > arr[j+1] {
				swap(arr, j, j+1)
				flag = true
			}
		}
		if flag == false {
			break
		}
	}
}

func swap(arr []int, i, j int) {
	tem := arr[i]
	arr[i] = arr[j]
	arr[j] = tem
}

最差时间复杂度:O(n2)
最佳时间复杂度:O(n)

方式四:内循环优化
记录最后一次交换的位置,如果后边没有交换数值,则数组必然是有序的,然后下一次排序从第一个比较到上次记录的位置结束
i : 已排好序的序列的左边界索引
j:用来遍历数组,进行冒泡操作
flag:判断数组是否已经有序
pos:记录上一次交换元素的元素位置
newPos: 临时变量

package main

import "fmt"

func main() {
	arr := []int{1, 7, 6, 7, 98, 9, -1, 7, 89, 14, -4, -5, -657}
	bubbleSort(arr)
	for _, v := range arr {
		fmt.Println(v)
	}
}

func bubbleSort(arr []int) {
	for i := len(arr) - 1; i > 0; i-- {
		flag := false
		pos, newPos := i, 0
		for j := 0; j < pos; j++ {
			if arr[j] > arr[j+1] {
				swap(arr, j, j+1)
				flag = true
				newPos = j
			}
		}
		if flag == false {
			break
		}
		pos = newPos
	}
}

func swap(arr []int, i, j int) {
	tem := arr[i]
	arr[i] = arr[j]
	arr[j] = tem
}

最差时间复杂度:O(n2)
最佳时间复杂度:O(n)

方式五:双向遍历优化(鸡尾酒排序)
记录最后一次交换的位置,如果后边没有交换数值,则数组必然是有序的,然后下一次排序从第一个比较到上次记录的位置结束
left : 左侧已排好序的序列的右边界索引
right:右侧已排好序的序列的左边界索引

package main

import "fmt"

func main() {
	arr := []int{1, 7, 6, 7, 98, 9, -1, 7, 89, 14, -4, -5, -657}
	bubbleSort(arr)
	for _, v := range arr {
		fmt.Println(v)
	}
}

func bubbleSort(arr []int) {
	left, right := 0, len(arr)-1
	for left < right {
		preBubbleSort(arr, left)
		left++
		if left >= right {
			break
		}
		backBubbleSort(arr, right)
		right--
	}

}

func preBubbleSort(arr []int, left int) {
	for i := left + 1; i < len(arr); i++ {
		if arr[i] < arr[left] {
			swap(arr, i, left)
		}
	}
}

func backBubbleSort(arr []int, right int) {
	for i := right - 1; i >= 0; i-- {
		if arr[i] > arr[right] {
			swap(arr, i, right)
		}
	}
}

func swap(arr []int, i, j int) {
	tem := arr[i]
	arr[i] = arr[j]
	arr[j] = tem
}

最差时间复杂度:O(n2)
最佳时间复杂度:O(n)

举报

相关推荐

0 条评论