常见排序算法
算法 | 时间复杂度 | 是否基于比较 |
---|---|---|
冒泡,插入,选择 | O(n^2) | 是 |
O(nlogn) | ||
O(n) |
排序算法分析
执行效率
- 最好,最坏,平均情况时间复杂度。
- 时间复杂度的系数,常数,低阶。
- 比较次数,交换(或移动)次数。
内存消耗
原地排序:特指空间复杂度为O(1)的排序算法。
稳定性
稳定的排序算法
不稳定的排序算法
冒泡排序
两两比较,数值大的沉下来,数值小的浮上去,依次比较选出较大的排列。
实现
package main
import "fmt"
func BubbleSort(arr map[int]int) {
n := len(arr)
if n <= 1 {
return
}
for i:=0;i<n;i++ {//控制比较次数
flag := false
for j:=0;j<n-1-i;j++ {
if arr[j] > arr[j+1] {
tmp := arr[j]
arr[j] = arr[j+1]
arr[j+1] = tmp
flag = true
}
}
if !flag {
break
}
}
return
}
func main() {
arr := make(map[int]int)
arr[0] = 1
arr[1] = 2
arr[2] = 7
arr[3] = 3
arr[4] = 5
arr[5] = 4
arr[6] = 6
BubbleSort(arr)
fmt.Println(arr)
}
复杂度
空间复杂度:O(1)
时间复杂度:最好是全有序的,比较n次O(n),最差逆序O(n^2),平均O(n^2)。
稳定性:稳定排序算法
原地排序
插入排序
数组分成两部分,前半部分有序,后半部分原样,维护两个指针,后半部分,从前往后遍历,取出要插入的元素,跟前半部分从后向前依次比较,找到合适的位置,并插入。
实现
package main
import "fmt"
func InsertSort(arr map[int]int) {
n := len(arr)
if n <= 1 {
return
}
for i := 1; i < n; i++ {
tmp := arr[i]
j := i-1
for ; j >= 0; j-- {
if tmp < arr[j] {
arr[j+1] = arr[j]
} else {
break
}
}
arr[j+1] = tmp
}
}
func SelectSort(arr map[int]int) {
n := len(arr)
if n <= 1 {
return
}
for i:=0;i<n;i++ {
for j:=i+1;j<n;j++ {
if arr[i] > arr[j] {
arr[i], arr[j] = arr[j], arr[i]
}
}
}
}
func PrintArr(arr map[int]int) {
for i:=0;i<len(arr);i++ {
fmt.Printf("%d : %d\n", i, arr[i])
}
}
func main() {
arr := make(map[int]int)
arr[0] = 1
arr[1] = 2
arr[2] = 7
arr[3] = 3
arr[4] = 5
arr[5] = 4
arr[6] = 6
InsertSort(arr)
PrintArr(arr)
}
复杂度
稳定性:稳定排序算法
空间复杂度:O(1)
时间复杂度:最好是全有序的,比较n次O(n),最差逆序O(n^2),平均O(n^2).
原地排序
选择排序
选择排序与插入排序类似,也是分已排序区间和未排序区间,不过选择排序是每次都在未排序区间选择最小的,放到已排序区间的末尾位置。
实现
见插入排序代码,比较来看。
总结
- 二者都是原地排序,时间复杂度都是O(n^2),二者排序比较的次数都等于数组的逆序度。
- 但冒泡排序的赋值语句是三条,插入排序关键赋值语句是一条。所以具体的排序操作,插入比冒泡赋值更加简单,更加节省时间。
- 选择排序因为每次都是找剩余中最小的跟前面的值交换,如5,8,5,2,6第一次找到最小的2,与首位的5交换位置,这样第一个5和第二个5顺序就变了,所以不是稳定排序。
-
原地排序 稳定性 最好时间复杂度 最坏时间复杂度 平均时间复杂度 欢迎程度 插入排序 是 是 O(n) O(n^2) O(n^2) 高 冒泡排序 是 是 O(n) O(n^2) O(n^2) 中 选择排序 是 否 O(n^2) O(n^2) O(n^2) 差
GO数组时间代码借鉴
package _1_sorts
/*
冒泡排序、插入排序、选择排序
*/
//冒泡排序,a是数组,n表示数组大小
func BubbleSort(a []int, n int) {
if n <= 1 {
return
}
for i := 0; i < n; i++ {
// 提前退出标志
flag := false
for j := 0; j < n-i-1; j++ {
if a[j] > a[j+1] {
a[j], a[j+1] = a[j+1], a[j]
//此次冒泡有数据交换
flag = true
}
}
// 如果没有交换数据,提前退出
if !flag {
break
}
}
}
// 插入排序,a表示数组,n表示数组大小
func InsertionSort(a []int, n int) {
if n <= 1 {
return
}
for i := 1; i < n; i++ {
value := a[i]
j := i - 1
//查找要插入的位置并移动数据
for ; j >= 0; j-- {
if a[j] > value {
a[j+1] = a[j]
} else {
break
}
}
a[j+1] = value
}
}
// 选择排序,a表示数组,n表示数组大小
func SelectionSort(a []int, n int) {
if n <= 1 {
return
}
for i := 0; i < n; i++ {
// 查找最小值
minIndex := i
for j := i + 1; j < n; j++ {
if a[j] < a[minIndex] {
minIndex = j
}
}
// 交换
a[i], a[minIndex] = a[minIndex],a[i]
}
}