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
}