排序算法 | 时间复杂度 | 最好情况 | 最坏情况 | 空间复杂度 | 排序方式 | 稳定性 |
---|---|---|---|---|---|---|
冒泡排序 | O(n^2) |
O(n^2) |
O(n) |
O(1) |
内部排序 | 稳定 |
选择排序 | O(n^2) |
O(n^2) |
O(n^2) |
O(1) |
内部排序 | 不稳定 |
插入排序 | O(n^2) |
O(n^2) |
O(n) |
O(1) |
内部排序 | 稳定 |
希尔排序 | O(nlog²n) |
O(nlogn) |
O(n^2) |
O(1) |
内部排序 | 不稳定 |
归并排序 | O(nlogn) |
O(nlogn) |
O(nlogn) |
O(n) |
外部排序 | 稳定 |
快速排序 | O(nlogn) |
O(nlogn) |
O(n^2) |
O(logn) |
内部排序 | 不稳定 |
堆排序 | O(nlogn) |
O(nlogn) |
O(nlogn) |
O(1) |
内部排序 | 不稳定 |
计数排序 | O(n+k) |
O(n+k) |
O(n+k) |
O(k) |
外部排序 | 稳定 |
桶排序 | O(n+k) |
O(n+k) |
O(n^2) |
O(n+k) |
外部排序 | 稳定 |
基数排序 | O(n*k) |
O(n*k) |
O(n*k) |
O(n+k) |
外部排序 | 稳定 |
nums都是切片传递
冒泡
func sort(nums []int) {
for i := 0; i < len(nums) - 1; i++ {
for j := 0; j < n-1-i; j++ {
if nums[j] > nums[j+1] {
nums[j], nums[j+1] = nums[j+1],nums[j]
}
}
}
}
选择
func sort(nums []int) {
for i := 0; i < n; i ++ {
minIndex := i
for j = i+1; j < n; j++ {
if nums[j] < nums[minIndex] {
minIndex = j
}
}
if minIndex != i {
nums[i], nums[minIndex] = nums[minIndex], nums[i]
}
}
}
与冒泡排序相比,选择排序每次找到后面最小的 与当前位置交换
插入排序
func sort(nums []int) {
n := len(nums)
for i:=1; i < n; i++ {
key := nums[i]
j := i-1
for j >= 0 && nums[j] > key {
nums[j+1] = nums[j]
j--
}
nums[j+1] = nums[j]
}
}
希尔排序
func sort(nums []int) {
n := len(nums)
gap := n/2
for gap > 0 {
for i := gap;i < n; i++ {
key := nums[i]
j := i
for j >= gap && nums[j-gap] > key {
nums[j] = nums[j-gap]
j-=gap
}
nums[j] = key
}
gap /= 2
}
}
插入排序的改进版
举个例子
[1,2,5,4,3,5,6,7,5,3,1]
11个元素 gap初始值为5
1, 5, 1
2, 6
5, 7
4, 5
3, 3
之后gap更新为2
1, 5, 3, 6, 5, 5
2, 4, 1, 7, 3
最后更新为1的时候排序完成 一句话总结的话,就是分组的插入排序
归并排序
func merge(left, right []int) []int {
res := []int{}
i, j := 0,0
for i < len(left) && j < len(right) {
if left[i] < right[j] {
res = append(res, left[i])
i++
}else {
res = append(res, right[i])
j++
}
}
res =append(res, left[i:]...)
res = append(res, right[j:]...)
return res
}
func mergeSort(arr []int) []int {
if len(arr) <= 1{
return arr
}
mid = len(arr)/2
left := mergeSort(arr[:mid])
right := mergeSort(arr[mid:])
return merge(left, right)
}
分治法
快速排序
func partition (arr []int, low, high int) int {
mid := low + (high - low) / 2
pivotC := []int{arr[low], arr[mid], arr[high]}
sort.Ints(pivotC)
pivot := pivotC[1]
if pivot == arr[low] {
arr[low], arr[high] = arr[high],arr[low]
}else if pivot == arr[mid] {
arr[mid], arr[high] = arr[high], arr[mid]
}
//把枢纽移动到末尾
i := low - 1
for j := low; j < high; j++ {
if arr[j] < pivot {
i++
arr[i], arr[j] = arr[j], arr[i]
}
}
arr[i+1], arr[high] = arr[high], arr[i+1]
return i+1
}
func quickSort(arr []int, low, high int) {
if low < high {
pi := partition(arr, low, high)
quickSort(arr, low, pi -1)
quickSort(arr, pi+ 1 , high)
}
}
堆排序
func heapSort(arr []int) {
n := len(arr)
for i := n/2-1; i >= 0; i-- {
heapify(arr, n, i)
}
for i :=n-1; i > 0; i-- {
arr[0], arr[i] = arr[i], arr[0]
heapify(arr, i, 0)
}
}
func heapify(arr []int, n, i int) {
largest := i
left := 2*i +1
right := 2*i +2
if left < n && arr[left] > arr[largest] {
largest = left
}
if right < n && arr[right] > arr[largest] {
largest = right
}
if largest != i {
arr[i], arr[largest] = arr[largest], arr[i]
heapify(arr,n, largest)
}
}
计数排序
func sort (arr []int) {
maxVal := 0
for _, num := range arr {
if num > maxVal {
maxVal = num
}
}
count := make([]int, maxVal+1)
for _, num := range arr {
count[num]++
}
idx := 0
for i := 0; i <= maxVal; i++ {
for count[i] > 0 {
arr[idx] = i
idx++
count[i]--
}
}
}
桶排序
func sort(arr []int) {
if len(arr) == 0 {
return
}
minVal, maxVal := arr[0], arr[0]
for _, num := range arr {
if num < minVal {
minVal = num
}
if num > maxVal {
maxVal = num
}
}
if maxVal == minVal {
return
}
//找到最大值和最小值
bucketCount := int(math.Sqrt(float64(len(arr))))
buckets := make([][]int, bucketCount)
for _, num := range arr {
// 计算每个元素应该放在哪个桶
ratio := float64(num-minVal) / float64(maxVal-minVal)
index := int(ratio * float64(bucketCount))
if index == bucketCount {
index--
}
buckets[index] = append(buckets[index], num)
}
index := 0
for i := 0; i < bucketCount; i++ {
// 对每个桶内部进行排序
sort.Ints(buckets[i])
for _, num := range buckets[i] {
arr[index] = num
index++
}
}
}
基数排序
func radixSort(arr []int) {
maxVal := arr[0]
for _, num := range arr {
if num > maxVal {
maxVal = num
}
}
exp := 1
for maxVal/exp > 0 {
countingSort(arr, exp)
exp *= 10
}
}
func countingSort(arr []int, exp int) {
n := len(arr)
output := make([]int, n)
count := make([]int, 10)
for i := 0; i < n; i++ {
digit := (arr[i]/exp)%10
count[digit]++
}
for i := 1; i < 10; i++ {
count[i] += count[i-1]
}
for i := n-1; i >= 0; i-- {
digit := (arr[i]/exp)%10
output[count[digit]-1] = arr[i]
count[digit]--
}
copy(arr,output)
}