算法思路:
从第一个元素开始,两两比较相邻两个元素数值的大小,数值大的放在后面(从小到大排列)
平均时间复杂度: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)