老规矩,上来先表示对原作者的敬重之心:n*log(3)n排序算法 -- 修江的芦苇
关于三叉堆排序呢,对于已经理解了二叉堆排序的人来说,其实很容易理解。该讲的在原作里面,作者已经讲的很清楚了,这里就只贴一下代码了。
首先是 heap.go:
package heap // import "triple-heap"
import "sort"
type Interface interface {
sort.Interface
Push(x interface{})
Pop() interface{}
}
func Init(h Interface) {
n := h.Len()
for i := n/3 - 1; i >= 0; i-- {
down(h, i, n)
}
}
func Push(h Interface, x interface{}) {
h.Push(x)
up(h, h.Len()-1)
}
func Pop(h Interface) interface{} {
n := h.Len() - 1
h.Swap(0, n)
down(h, 0, n)
return h.Pop()
}
func Remove(h Interface, i int) interface{} {
n := h.Len() - 1
if n != i {
h.Swap(i, n)
down(h, i, n)
up(h, i)
}
return h.Pop()
}
func Fix(h Interface, i int) {
down(h, i, h.Len())
up(h, i)
}
func up(h Interface, j int) {
for {
i := (j - 1) / 3 // parent
if i == j || !h.Less(j, i) {
break
}
h.Swap(i, j)
j = i
}
}
func down(h Interface, i, n int) {
for {
j1 := 3*i + 1
if j1 >= n || j1 < 0 { // j1 < 0 after int overflow
break
}
j := j1 // left child
if j2 := j1 + 1; j2 < n && !h.Less(j, j2) {
j = j2 // = 3*i + 2 // mid child
}
if j3 := j1 + 2; j3 < n && !h.Less(j, j3) {
j = j3 // = 3*i + 3 // right child
}
if !h.Less(j, i) {
break
}
h.Swap(i, j)
i = j
}
}
接下来是 sort.go:
package main
import (
"fmt"
"triple-heap"
)
type myHeap []int
func (h *myHeap) Less(i, j int) bool {
return (*h)[i] < (*h)[j]
}
func (h *myHeap) Swap(i, j int) {
(*h)[i], (*h)[j] = (*h)[j], (*h)[i]
}
func (h *myHeap) Len() int {
return len(*h)
}
func (h *myHeap) Pop() (v interface{}) {
*h, v = (*h)[:h.Len()-1], (*h)[h.Len()-1]
return
}
func (h *myHeap) Push(v interface{}) {
*h = append(*h, v.(int))
}
func TripleHeapSort(h heap.Interface) {
heap.Init(h)
var t = make([]interface{}, 0, h.Len())
for h.Len() > 0 {
t = append(t, heap.Pop(h))
}
for i := 0; i < len(t); i++ {
h.Push(t[i])
}
}
func main() {
var h = myHeap{5, 3, 1, 9, 0, 6, 4, 7, 8, 2}
fmt.Println(h)
TripleHeapSort(&h)
fmt.Println(h)
}
运行 go run sort.go结果:
[5 3 1 9 0 6 4 7 8 2]
[0 1 2 3 4 5 6 7 8 9]
对于包的组织和管理,大家自己去搞咯~
好啦,本期节目到此为止,咱们下期再见!