Golang implementation of the Fibonacci heap

Source: Internet
Author: User
This is a creation in Article, where the information may have evolved or changed.

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.


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;&AMP;&AMP;&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

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.