package main import "fmt" func main() { arr := []int{8, 9, 5, 7, 1, 2, 5, 7, 6, 3, 5, 4, 8, 1, 8, 5, 3, 5, 8, 4} //result := mergeSort(arr) result := buckerSort(arr) fmt.Println(result, arr) } //要求在O(nlogn)的時間複雜度下排序鏈表,且時間複雜度在O(1) // //涉及到O(logn)的算法有 // //二分法 //快速排序 //歸併排序 //堆排序 //二分法一般應用在已排序的序列中,且經常使用語查找算法,而不用做排序算法 // 冒泡排序:O(n^2) // 外層循環 0到n-1 //控制比較輪數 n 表示元素的個數 // 內層循環 0到n-i-1 //控制每一輪比較次數 // 兩兩比較作交換 func bubbleSort(data []int) { if len(data) < 2 { return } for i := 0; i < len(data)-1; i++ { for j := 0; j < len(data)-i-1; j++ { if data[j] > data[j+1] { data[j], data[j+1] = data[j+1], data[j] } } } } // 快速排序:O(n*logn) // i, j := left, right,將左邊第一個數挖出來做爲基準。 // j--由後向前找比它小的數,找到後挖出此數填前一個坑a[i]中。 // i++由前向後找比它大的數,找到後也挖出此數填到前一個坑a[j]中。 // 再重複執行2,3二步,直到i==j,將基準數填入a[i]中。 func quickSort(data []int, left, right int) { fmt.Println("every000: ", left, right) if left >= right { return } i, j := left, right x := data[left] for i < j { for i < j && data[j] > x { j-- } data[i] = data[j] for i < j && data[i] <= x { i++ } data[j] = data[i] } fmt.Println("every: ", data) data[i] = x quickSort(data, left, i-1) quickSort(data, i+1, right) } // 歸併排序:O(n*log(n)) // 創建在歸併操做上的一種有效的排序算法。該算法是採用分治法(Divide and Conquer)的一個很是典型的應用 // 先分治 -> 再合併 func mergeSort(arr []int) []int { if len(arr) < 2 { return arr } i := len(arr) / 2 left := mergeSort(arr[0:i]) right := mergeSort(arr[i:]) result := merge(left, right) return result } func merge(left, right []int) []int { result := make([]int, 0) m, n := 0, 0 // left和right的index位置 l, r := len(left), len(right) for m < l && n < r { if left[m] > right[n] { result = append(result, right[n]) n++ //continue } else { result = append(result, left[m]) m++ } } result = append(result, right[n:]...) // 這裏居然沒有報數組越界的異常? result = append(result, left[m:]...) return result } // 堆排序:O(n*log(n)) https://blog.csdn.net/code_beeps/article/details/91488526 // s[0]不用,實際元素從角標1開始 // 父節點元素大於子節點元素 // 左子節點角標爲2*k // 右子節點角標爲2*k+1 // 父節點角標爲k/2 func HeapSort(s []int) { N := len(s) - 1 //s[0]不用,實際元素數量和最後一個元素的角標都爲N //構造堆 //若是給兩個已構造好的堆添加一個共同父節點, //將新添加的節點做一次下沉將構造一個新堆, //因爲葉子節點均可看做一個構造好的堆,因此 //能夠從最後一個非葉子節點開始下沉,直至 //根節點,最後一個非葉子節點是最後一個葉子 //節點的父節點,角標爲N/2 for k := N / 2; k >= 1; k-- { sink(s, k, N) } //下沉排序 for N > 1 { s[1], s[N] = s[N], s[1] //將大的放在數組後面,升序排序 N-- sink(s, 1, N) } } //下沉(由上至下的堆有序化) func sink(s []int, k, N int) { for { i := 2 * k if i > N { //保證該節點是非葉子節點 break } if i < N && s[i+1] > s[i] { //選擇較大的子節點 i++ } if s[k] >= s[i] { //沒下沉到底就構造好堆了 break } s[k], s[i] = s[i], s[k] k = i } } // 桶排序:O(n) // 藉助一個一維數組就能夠解決這個問題 // 最大數值做爲這個數組的長度,數組的下標key等於這元素的,value就+1 func buckerSort(s []int) []int { arr := make([]int, 10) for _, v := range s { arr[v] += 1 } sortList := make([]int, 0, len(s)) for k, v := range arr { if v > 0 { for i := 0; i < v; i++ { sortList = append(sortList, k) } } } return sortList }