经典算法-排序(golang)
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(data []int) []int { if len(data) < 2 { return data } mid := len(data) >> 1 left := mergeSort(data[:mid]) right := mergeSort(data[mid:]) result := merge(left, right) return result } func merge(left, right []int) []int { list := 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] { list = append(list, left[m]) m++ } else { list = append(list, right[n]) n++ } } list = append(list, left[m:]...) list = append(list, right[n:]...) return list } // 堆排序:O(n*log(n)) func HeapSort(c []int) { var n = len(c) for root := n/2 - 1; root >= 0; root-- { fmt.Println(root, n-1, c) maxHeap(root, n-1, c) } fmt.Println("大根堆构建完成", c) for end := n; end >= 0; end-- { c[0], c[end] = c[end], c[0] maxHeap(0, end-1, c) } } func maxHeap(root int, end int, c []int) { for { var child = 2*root + 1 // 左子节点为2n+1,右子节点为2n+2 //判断是否存在child节点 if child > end { break } //判断右child是否存在,如果存在则和另外一个同级节点进行比较 if child+1 <= end && c[child+1] > c[child] { child += 1 } // 找左右子节点最大的那个与父节点root比较,交换 // 然后将child赋值到root,继续下沉 if c[child] > c[root] { c[root], c[child] = c[child], c[root] root = child } else { break } } } // 桶排序: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 }
// 二分查找法,返回索引 func BinarySearch(nums []int, target int) int { l, r := 0, len(nums)-1 for l <= r { mid := l + (r-l) >> 1 temp := nums[mid] if temp == target { return mid } if target < temp { r = mid-1 }else { l = mid+1 } } return -1 }