参考:
概念 首先, 排序是指, 将一个数组中的元素按照特定顺序放置, 并不一定是从小到大或者从大到小, 排序的最终目的, 很大时候是为了查找方便
稳定性 算法的稳定性是指, 按照他们在输入中出现的位置对相同的元素进行排序. 也就是说, 对于每个输入的需要排序的元素, 我们按照某个key进行排序, 如果这两个key相同, 那么他们的顺序应该是他们输入的时候原来的对应前后位置.
例如一个数组
1 [(3, a), [3, b], (1, m)]
我们对上面的数组, 按每个元素的m[0]为key进行排序, 如果我们采用的算法是稳定的, 那么结果应该是:
O符号对于一个排序算法的性能比较, 经常出现的一个符号是O, 这个应该叫做渐进符号, 我们采用O来标示算法的性能, 是指我们只关注算法消耗资源增长的数量级:
如果f(x)是几个项的总和, 如果有一个具有最大增长率的项, 那么我们保留这个, 忽略其他的项
如果f(x)是几个因子的乘积, 则可以忽略所有的常数
算法实现 下面涉及的算法如果没有特殊说明, 那么应该是完成数组从小到大的排列
选择排序 选择排序可以理解为, 数组最左边的value一定是数组中最小的值. 那么实现就应该是从数组中取出最小的那个value, 然后放到数组的最左边, 依次递归下去
1 2 3 4 5 6 7 8 9 10 11 12 func SelectionSortDoc (arr []int ) []int { length := len (arr) for i := 0 ; i < length; i++ { for j := i+1 ; j < length; j++ { if arr[i] > arr[j] { arr[i], arr[j] = arr[j], arr[i] } } } return arr }
上面是最简单的实现, 但是我们看下这一步:
1 2 3 if arr[i] > arr[j] { arr[i], arr[j] = arr[j], arr[i] }
每碰到一个arr[i]大于arr[j]的数, 两个就要交换一下, 这样做了很多重复性的工作, 对吧, 因为我们只需要将arr[i]和arr[i:]中最小的那个作交换就可以了:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 func SelectionSortDocM (arr []int ) []int { length := len (arr) for i := 0 ; i < length; i++ { min := i for j := i+1 ; j < length; j++ { if arr[min] > arr[j] { min = j } } if min != i { arr[i], arr[min] = arr[min], arr[i] } } return arr }
插入排序 插入排序就是将一个值插入到一个已经排好序的数组中.
插入排序可以理解为在一个排好序的数组arr[1,2,3...k, k+1, ...n]中, 每一个子数组arr[0:k]都是一个排好序的数组:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 func InsertionSort (arr []int ) []int { length := len (arr) for i := 1 ; i < length; i++ { j := i - 1 key := arr[i] for j >= 0 && arr[j] > key { arr[j+1 ] = arr[j] j -= 1 } arr[j+1 ] = key } return arr }
快速排序 快速排序的思想是, 一个排好序的数组arr[1,2,3..., k, k+1... n]中, 一定有:
子数组arr[0:k]中的每一个值都不大于arr[k]
子数组arr[k+1:n]中的每一个值都不小于arr[k]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 func QuickSortDoc (arr []int ) []int { var recurse func (left, right int ) // 找到数组中迭代每一次子数组中根据key 排序的key 的位置, // 这时候key 应该是排好序的数组中的正确位置 var partition func (left, right int ) int partition = func (left, right int ) int { key := arr[right] j := left for i := left; i < right; i++ { if arr[i] < key { arr[j], arr[i] = arr[i], arr[j] j++ } } arr[j], arr[right] = arr[right], arr[j] return j } recurse = func (left, right int ) { if left < right { pivot := (right+left) / 2 pivot = partition(left, right) recurse(left, pivot-1 ) recurse(pivot+1 , right) } } recurse(0 , len (arr)-1 ) return arr }
归并排序 // TODO 这个没有看懂, python版本的转换不到go上
归并排序的思想是合并两个已经排好序的列表形成新的列表:
将未排序的列表分成n个子列表,每个子列表包含1个元素(1个元素的列表被认为是排序的).
反复合并子列表以产生新的已排序子列表,直到只剩下1个子列表。这将是排序的列表。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 def merge (a, b) : k = j = 0 c = [] while k < len(a) and j < len(b): key_a = a[k] key_b = b[j] if key_a < key_b: c.append(key_a) k += 1 else : c.append(key_b) j += 1 c.extend(a[k:]) c.extend(b[j:]) return c def mergeSort (lst) : if len(lst) < 2 : return lst mid = len(lst) // 2 left = mergeSort(lst[:mid]) right = mergeSort(lst[mid:]) return merge(left, right)
go版本:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 func sort (arr []int ) { var s = make ([]int , len (arr)/2 +1 ) if len (arr) < 2 { return } mid := len (arr) / 2 sort(arr[:mid]) sort(arr[mid:]) if arr[mid-1 ] <= arr[mid] { return } copy (s, arr[:mid]) l, r := 0 , mid for i := 0 ; ; i++ { if s[l] <= arr[r] { arr[i] = s[l] l++ if l == mid { break } } else { arr[i] = arr[r] r++ if r == len (arr) { copy (arr[i+1 :], s[l:mid]) break } } } return }
堆排序 没写完还…
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 package heapimport ( "sync" ) type Int int func (x Int) Less (than Item) bool { return x < than.(Int) } type Item interface { Less(than Item) bool } type Heap struct { sync.Mutex data []Item min bool } func New () *Heap { return &Heap{ data: make ([]Item, 0 ), } } func NewMin () *Heap { return &Heap{ data: make ([]Item, 0 ), min: true , } } func NewMax () *Heap { return &Heap{ data: make ([]Item, 0 ), min: false , } } func (h *Heap) isEmpty () bool { return len (h.data) == 0 } func (h *Heap) Len () int { return len (h.data) } func (h *Heap) Get (n int ) Item { return h.data[n] } func (h *Heap) Insert (n Item) { h.Lock() defer h.Unlock() h.data = append (h.data, n) h.siftUp() return } func (h *Heap) Extract () (el Item) { h.Lock() defer h.Unlock() if h.Len() == 0 { return } el = h.data[0 ] last := h.data[h.Len()-1 ] if h.Len() == 1 { h.data = nil return } h.data = append ([]Item{last}, h.data[1 :h.Len()-1 ]...) h.siftDown() return } func (h *Heap) siftUp () { for i, parent := h.Len()-1 , h.Len()-1 ; i > 0 ; i = parent { parent = i >> 1 if h.Less(h.Get(i), h.Get(parent)) { h.data[parent], h.data[i] = h.data[i], h.data[parent] } else { break } } } func (h *Heap) siftDown () { for i, child := 0 , 1 ; i < h.Len() && i<<1 +1 < h.Len(); i = child { child = i<<1 + 1 if child+1 <= h.Len()-1 && h.Less(h.Get(child+1 ), h.Get(child)) { child++ } if h.Less(h.Get(i), h.Get(child)) { break } h.data[i], h.data[child] = h.data[child], h.data[i] } } func (h *Heap) Less (a, b Item) bool { if h.min { return a.Less(b) } else { return b.Less(a) } }
python版本的:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 def opt_heapsort (s) : sl = len(s) def swap (pi, ci) : if s[pi] < s[ci]: s[pi], s[ci] = s[ci], s[pi] def sift (pi, unsorted) : i_gt = lambda a, b: a if s[a] > s[b] else b while pi*2 +2 < unsorted: gtci = i_gt(pi*2 +1 , pi*2 +2 ) swap(pi, gtci) pi = gtci for i in range((sl//2 )-1 , -1 , -1 ): sift(i, sl) for i in range(sl-1 , 0 , -1 ): swap(i, 0 ) sift(0 , i)
树排序 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 func main () { a := []int {9 ,5 ,3 ,5 ,2 ,1 } TreeSort(a) fmt.Println(a) } type tree struct { value int left, rigth *tree } func TreeSort (values []int ) { var root *tree for _, value := range values { root = add(root, value) } appendValues(values[:0 ], root) } func appendValues (values []int , root *tree) []int { if root != nil { values = appendValues(values, root.left) values = append (values, root.value) values = appendValues(values, root.rigth) } return values } func add (t *tree, value int ) *tree { if t == nil { t = new (tree) t.value = value return t } if value < t.value { t.left = add(t.left, value) } else { t.rigth = add(t.rigth, value) } return t }