The binary heap provides an O (LGN) time insertion, the deletion of minimal, degraded operations, and O (n) time merging operations; The Fibonacci heap provides a better operating time limit: O (1) insertion, O (LGN) Delete minimum, O (LGN) Delete, O (1) Merge. According to the introduction to the algorithm, the Fibonacci heap is particularly useful when deleting a minimum or delete operation is performed much less often than other operations. Some of the graph's algorithms (Calculate minimum spanning tree, single source shortest path) as the basic building blocks (as priority teams).
Given the complexity of Fibonacci implementations, it is possible that binary stacks are more usable in practice. Just like Rob Pike in the <notes on programming in C> said:
3. Fancy algorithms are usually very slow in n hours, while n is usually very small. The constant complexity of fancy algorithms is very large. Do not use fancy algorithms unless you are sure that N is always large .
4. fancy algorithms are more prone to bugs and more difficult to implement than simple algorithms. Try to use simple algorithms in conjunction with simple data structures.
The following implementations refer to: www.cs.princeton.edu/~wayne/teaching/ Fibonacci - Heap . pdf, Introduction to the 19th chapter of the algorithm.
Fiboheap.go
package mainimport ("container/ring" "Log" "unsafe") type fibonode struct {mark bool //record whether the node has just lost a second child, the downgrade operation uses this property degree int //recorded below a couple of children hooked up child, parent *fibonode //child points to the child's linked list, and the parent points to the ring. ring //borrowed the existing Ring implementation of the standard library}// The client provides a node comparison function implementation, in order to perform the delete node operation, the comparison function implementation, assuming nil value less than non-nil value. Type less func (a, b interface{}) bool//similar to the hack method commonly used in C, the methods of anonymous field types are promoted to external types func Container_of (in *ring. RING,&NBSP;OFF&NBSP;UINTPTR) *FiboNode {f := (*fibonode) (unsafe. Pointer (UIntPtr (unsafe. Pointer (in)) - off) return f}func (R *fibonode) link (S *fibonode) * Fibonode {off := unsafe. Offsetof (r.ring) return container_of (R.link (&s.ring), &NBsp;off)}func (R *fibonode) unlink (n int) *fibonode {off := unsafe. Offsetof (r.ring) return container_of (R.unlink (n), off)}func (R *fibonode) prev () *fibonode {off := unsafe. Offsetof (r.ring) return container_of (R.prev (), off)}func (R *fibonode) next () * Fibonode {off := unsafe. Offsetof (r.ring) return container_of (R.next (), off)}func (R *fibonode) move (n int ) *fibonode {off := unsafe. Offsetof (r.ring) return container_of (R.move (n), off)}//n nodes fibonacci heap the upper bound is Math.floor (Math.log (n, 1.618))//So pre-allocated an array of 64 size, the maximum number of nodes to accommodate &NBSP;&NBSP;MATH.POW (1.618, 64)// Eliminates the reallocation of consolidate operations every time you enter type fiboheap struct {min *fibonode //record the current minimum node n int Number of nodes in //heap degtab [64]*fibonode // Records the degree of a node in the root table less less //Client provides comparison function implementation}func new (less less) *fiboheap {if less == nil {return nil}return &FiboHeap{less: less}}func (FH&NBSP;*FIBOHEAP) Insert (val interface{}) *fibonode {fn := &fibonode{ring: ring. Ring{value: val}}if fh.min == nil {fh.min = fn} else {fh.min.link (FN) if fh.less (val, fh.min.value) {fh.min = fn}}fh.n++return fn}func join ( fh, oh *fiboheap, less less) *FiboHeap {if fh == nil & & oh == nil {return nil} else if fh == nil && oh != nil {return OH}&NBSP;ELSE&NBSP;IF&NBSP;FH&NBSP;!=&NBSP;NIL&NBSP;&&&NBSP;OH&NBSP;==&NBSP;NIL&NBSP;{RETURN&NBSP;FH} else {nh := new (less) if fh.min != nil && oh.min == nil {nh.min = fh.minnh.n = fh.n} else if fh.min == nil && oh.min != nil {nh.min = oh.minnh.n = oh.n} else if fh.min != nil && oh.min != nil {fh.min.link (Oh.min) if less (Oh.min.value, fh.min.value) {nh.min = oh.min} else {nh.min = fh.min}nh.n = fh.n + oh.n}return nh}}func (fh *fiboheap) delmin ( ) *fibonode {z := fh.minif z != nil {first := z.child//log. Println (first, " ", z.degree, " ", off) for i := z.degree; i > 0; i-- {c := first.unlink (1) c.parent = nilz.link (c)}z.child = Nilz.degree = 0//fh.min.do (func ( v interface{}) { log. Println (v) }) Th := z.prev ()//log. Printf ("th = %v, z = %v\n", th, z) if th == z {fh.min = nil//log. Println ("Heap will become empty")} else {th.unlink (1) fh.min = th//log. Printf ("fh.min = %v, z = %v\n", fh.min, z) Consolidate (FH)}fh.n--} Return z}func heaplink (Y, x *fibonode) {y.prev (). Unlink (1) y.parent = xif x.child == nil {x.child = y} else { X.child.link (y)}x.degree++y.mark = false}func consolidate (fh *fiboheap) {n := len (Fh.degtab) for i := 0; i < n; i++ {fh.degtab[i] = nil}rootlist := make ([]*fibonode, 0) Rootlist = append (rootlist, fh.min) for x := Fh.min.next (); x != fh.min; x = x.next () {rootlist = append ( ROOTLIST,&NBSP;X)}for _, x := range rootlist {/*log. Printf ("in range x=%v\n", x.value) if x.child != nil { x.child.do (func (v interface{}) {log. Println (v)}) }*/d := x.degreetab := fh.degtab[:]for tab[d] != Nil {y := tab[d]if fh.less (y.value, x.value) {x, y = y, x} Heaplink (y, x)//log. Printf ("y=%v, x=%v\n", y, x) Tab[d] = nild++}tab[d] = x}//log. Printf ("after, fh.degtab=%v\n", fh.degtab) For _, n := ranGe fh.degtab {if n != nil {fh.min = nbreak}}min := fh.minfor n := fh.min.next (); n != fh.min; n = n.next () {if Fh.less (n.value, min. Value) {min = n}}fh.min = min}func (fh *fiboheap) decreasekey (n * fibonode, val interface{}) {if fh.less (Val, n.value) {n.value = valp := n.parentif p != nil && fh.less (N.Value, p.Value) { Fh.cut (n, p) fh.cascadingcut (p)}if fh.less (N.value, fh.min.value) {fh.min = n}}} func (fh *fiboheap) cut (N, p *fibonode) {if n.prev () == n { P.child = nil} else {n.prev (). Unlink (1)}p.degree--fh.min.link (n) n.parent = niln.mark = false}func (fh * FIBOHEAP) cascadingcut (X *fibonode) {y :=&Nbsp;x.parentif y != nil {if x.mark == false {x.mark = true} else {fh.cut (x, y) fh.cascadingcut (y)}}}//delete operation, by setting the current node value to nil, comparison function let nil less than Non- nil, normal node should not contain nil value,//downgrade after, delete min func (fh *fiboheap) delnode (N *fibonode) *fibonode {fh. Decreasekey (N, nil) return fh. Delmin ()}func (fh *fiboheap) walk () {if fh.min == nil {return} Heapvisit (Fh.min) For c := fh.min.next (); c != fh.min; c = c.next ( ) {heapvisit (c)}}func heapvisit (C *fibonode) {if c == nil {return}log. Printf ("value:%v degree:%v mark:%v\n", c.value, c.degree, c.mark) if c.child != nil {heapvisit (C.child) for n := c.child.next (); n != c.child; n = n.next () {heapvisit (n)}}}
simple test: (probably best with testing package) Fibotest.go
package mainimport ("FMT" "Math/rand" "Time") Func main () {less := func (a, b interface{}) bool {if a == nil && b != nil { return true} else if a != nil && b == nil { return false} else if a == nil && b == nil { Return false}return a. (int) < b. (int)}less1 := func (a, b interface{ }) bool {if a != nil && b == nil {return false} else if a == nil && b != nil {return true} else if a == nil && b == nil {return false} Return a. (float64) < b. (float64)}_ = less1rand. Seed (time. Now (). Unixnano ()) fh := new (less)//arr := []int{661,704,997,400,917,278,508,817,561,660}for i := 0; i < 1000; i++ {//n := arr[i]n := rand. INTN (100000) FH. Insert (n)}//fmt. Println ("heap size ", &NBSP;FH.N)/* fh. Insert (9.32) a := fh. Insert (10.439) fh. Decreasekey (a, 7.890) fh. Insert (8.43439) fh. Insert (100.1) b := fh. Insert (1000.88) fh. Insert (5.324) fh. Delnode (b) fh. Insert (3.6789) */for i := 0; i < 1000; i++ {fmt. Println (FH. Delmin (). Value)//fh. Walk ()}}
Go build-o fibotest fibotest.go fiboheap.go
Golang implementation of the Fibonacci heap