1、冒泡排序
整体思路:从前向后,依次比较相邻元素的值,若发现逆序则交换,使值较大的元素从前向后移动
简而言之,第i趟排序将第i大的数据移向length-i-1位
时间复杂度:O(n^2) 稳定的排序算法
package main
import(
"fmt"
)
func main(){
arr := []int{7,5,4,8,9,6,10,1,11}
// arr := []int{5,3,2}
arr1 := bubble(arr)
fmt.Println("排序后数组:", arr1)
}
func bubble(arr []int) []int{
lens := len(arr)
for i := 0; i < lens; i++ {
for j := 0; j < lens-i-1; j++ {
if arr[j] > arr[j+1]{
tmp := arr[j+1]
arr[j+1] = arr[j]
arr[j] = tmp
}
}
}
return arr
}
2、快速排序
基本思想:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分所有数据都比另一部分所有数据小,再按此方法对这两部分数分别进行快排(递归),使整个数据变为有序序列
时间复杂度:O(nlogn) ,不稳定的排序算法
package main
import(
"fmt"
)
func main(){
arr := []int{7,5,4,12,78,8,9,6,10,1,11}
// arr := []int{5,3,2}
fmt.Println("排序前数组:", arr)
arr1 := quickSortFunc(arr, 0, len(arr)-1)
fmt.Println("排序后数组:", arr1)
}
func quickSortFunc(arr []int, start int, end int) []int{
if start < end{
i,j := start, end
index := arr[(start+end)/2]
for i<=j {
for arr[j] > index{
j--
}
for arr[i] < index{
i++
}
if i <= j{
arr[i],arr[j] = arr[j], arr[i]
i++
j--
}
}
if start < j{ //向左递归
quickSortFunc(arr, start, j)
}
if end > i {//向右递归
quickSortFunc(arr, i, end)
}
}
return arr
}
3、插入排序
基本思想:把n个待排序元素看成一个有序表和无序表,开始时有序表中只包含一个元素,无序表中包含n-1个元素,每次从无序表中取出第一个元素,把它与有序表元素依次进行比较,插入到有序表适当的位置,使之成为新的有序表
时间复杂度:O(n^2) , 稳定的排序算法
//插入排序
func insertSort(arr []int) []int {
n := len(arr)
for i := 1; i < n; i++ {
insert := arr[i] //待插入的数
j := i - 1
if insert < arr[j] {
for ; j >= 0 && arr[j] > insert; j-- {
arr[j+1] = arr[j]
}
arr[j+1] = insert
}
}
return arr
}
4、选择排序
现在有一堆乱序的数,比如:5 9 1 6 8 14 6 49 25 4 6 3。
第一轮迭代,从第一个数开始,左边到右边进行扫描,找到最小的数 1,与数列里的第一个数交换位置。
第二轮迭代,从第二个数开始,左边到右边进行扫描,找到第二小的数 3,与数列里的第二个数交换位置。
第三轮迭代,从第三个数开始,左边到右边进行扫描,找到第三小的数 4,与数列里的第三个数交换位置。
第N轮迭代:…
经过交换,最后的结果为:1 3 4 5 6 6 6 8 9 14 25 49,我们可以看到已经排好序了。
时间复杂度:O(n^2), 运行时间实际低于冒泡排序,不稳定的排序算法
func selectSort(arr []int) []int {
n := len(arr)
for i := 0; i < n; i++ {
min := arr[i]
minIndex := i
for j := i + 1; j < n; j++ {
if min > arr[j] {
minIndex = j
min = arr[j]
}
}
if i != minIndex {
arr[i], arr[minIndex] = arr[minIndex], arr[i]
}
}
return arr
}
5、堆排序
根据灯神视频: https://www.bilibili.com/video/BV1Eb41147dK/?spm_id_from=333.1007.top_right_bar_window_custom_collection.content.click&vd_source=304ddde222ac891d9516a57f8192f02b
package main
import (
"fmt"
)
func main() {
tree := []int{2, 5, 3, 1, 10, 4}
n := 6
heapSort(tree, n)
// buildHeap(tree, n)
// heapify(tree, n, 0)
fmt.Println(tree)
}
// n表示数组tree的长度,i表示对哪个节点做heapify
func heapify(tree []int, n int, i int) {
if i >= n {
return
}
//节点i的两个孩子节点
c1 := 2*i + 1
c2 := 2*i + 2
max := i
if c1 < n && tree[c1] > tree[max] {
max = c1
}
if c2 < n && tree[c2] > tree[max] {
max = c2
}
if max != i {
tree[max], tree[i] = tree[i], tree[max]
heapify(tree, n, max)
}
}
func buildHeap(tree []int, n int) {
last := n - 1
//从最后一个parent节点依次向上做heapify,构造一个大顶堆
parent := (last - 1) / 2
for i := parent; i >= 0; i-- {
heapify(tree, n, i)
}
}
//堆排序
func heapSort(tree []int, n int) {
buildHeap(tree, n) //先构造一个堆
//从最后一个节点开始,依次和第0个节点交换
for i := n - 1; i >= 0; i-- {
tree[i], tree[0] = tree[0], tree[i]
heapify(tree, i, 0) //砍断最后一个节点,做heapify
}
}