github.com/zhiqiangxu/util@v0.0.0-20230112053021-0a7aee056cd5/rpheap/rank_pairing_heap.go (about)

     1  package rpheap
     2  
     3  type node struct {
     4  	item       int64
     5  	left, next *node // 对于root,next用于循环链表,指向下一棵半树;对于非root,next指向右儿子
     6  	rank       int
     7  }
     8  
     9  // Heap for rank pairing heap
    10  // zero value is an empty heap
    11  type Heap struct {
    12  	head *node // 指向循环链表的头部
    13  	size int
    14  }
    15  
    16  // New is ctor for Heap
    17  func New() *Heap {
    18  	return &Heap{}
    19  }
    20  
    21  type heapInterface interface {
    22  	Insert(val int64)
    23  	FindMin() int64
    24  	// 传入的heap将清零
    25  	Meld(*Heap)
    26  	DeleteMin() int64
    27  	Size() int
    28  	Clear()
    29  }
    30  
    31  var _ heapInterface = (*Heap)(nil)
    32  
    33  // Insert into the heap
    34  func (h *Heap) Insert(val int64) {
    35  	ptr := &node{item: val}
    36  	h.insertRoot(ptr)
    37  	h.size++
    38  }
    39  
    40  func (h *Heap) insertRoot(ptr *node /*ptr 是根节点*/) {
    41  	if h.head == nil { // 第一棵半树
    42  		h.head = ptr
    43  		ptr.next = ptr // 循环链表
    44  	} else {
    45  		// 先把ptr串到header后面
    46  		ptr.next = h.head.next
    47  		h.head.next = ptr
    48  		// 如果ptr更小,将header指向ptr即可,这里体现了循环链表的灵活性
    49  		if ptr.item < h.head.item {
    50  			h.head = ptr
    51  		}
    52  	}
    53  }
    54  
    55  // FindMin from the heap
    56  func (h *Heap) FindMin() int64 {
    57  	if h.head == nil {
    58  		panic("FindMin on empty heap")
    59  	}
    60  	return h.head.item
    61  }
    62  
    63  // Meld two heaps
    64  func (h *Heap) Meld(a *Heap) {
    65  	if h.head == nil {
    66  		h.head = a.head
    67  		h.size = a.size
    68  		a.Clear()
    69  		return
    70  	}
    71  	if a.head == nil {
    72  		return
    73  	}
    74  
    75  	// 两个heap都非空
    76  	if h.head.item < a.head.item {
    77  		merge(h, a)
    78  	} else {
    79  		merge(a, h)
    80  		h.head = a.head
    81  		h.size = a.size
    82  	}
    83  
    84  	a.Clear()
    85  	return
    86  }
    87  
    88  func merge(a, b *Heap) {
    89  	// 前置条件是a、b非空
    90  	// 将b往a合并, 循环链表需要对长度为1的情况特殊处理下
    91  	if a.size == 1 {
    92  		ptr := a.head
    93  		ptr.next = nil
    94  		if ptr.left != nil || ptr.rank != 0 {
    95  			panic("size 1 heap with left or non-zero rank")
    96  		}
    97  		b.insertRoot(ptr)
    98  		b.size++
    99  		a.head = b.head
   100  		a.size = b.size
   101  		return
   102  	} else if b.size == 1 {
   103  		ptr := b.head
   104  		ptr.next = nil
   105  		if ptr.left != nil || ptr.rank != 0 {
   106  			panic("size 1 heap with left or non-zero rank")
   107  		}
   108  		a.insertRoot(ptr)
   109  		a.size++
   110  		return
   111  	}
   112  
   113  	// 两个链表长度都大于1
   114  	// 将b的第二个元素串到a的第一个元素后面
   115  	// 同时将a原先的第二个元素串到b的第一个元素后面
   116  	// 这样b的第二个元素最终会回到b的第一个元素,然后再到a原先的第二个元素,直到回到a的头部
   117  	// 便把两个链表合并了
   118  	a.head.next, b.head.next = b.head.next, a.head.next
   119  	a.size += b.size
   120  
   121  }
   122  
   123  // DeleteMin from the heap
   124  func (h *Heap) DeleteMin() int64 {
   125  	if h.head == nil {
   126  		panic("DeleteMin on empty heap")
   127  	}
   128  
   129  	h.size--
   130  	ret := h.head.item
   131  
   132  	bucket := make([]*node, h.maxBucketSize())
   133  	// 沿着root的唯一左child一路往右(包括左child本身),将root所在的树分解成若干棵半树,并对相同rank的树进行合并
   134  	for ptr := h.head.left; ptr != nil; {
   135  		// 先记录下右child,因为ptr要作为独立半树进行合并,next必须置为空
   136  		nextPtr := ptr.next
   137  		ptr.next = nil
   138  		mergeSubTreeByRank(bucket, ptr)
   139  		ptr = nextPtr
   140  	}
   141  	// 遍历所有半树串成的循环链表,首棵树除外
   142  	for ptr := h.head.next; ptr != h.head; {
   143  		nextPtr := ptr.next
   144  		ptr.next = nil
   145  		mergeSubTreeByRank(bucket, ptr)
   146  		ptr = nextPtr
   147  	}
   148  
   149  	// 将bucket中的所有半树插入到空heap
   150  	h.head = nil
   151  	for _, ptr := range bucket {
   152  		if ptr != nil {
   153  			h.insertRoot(ptr)
   154  		}
   155  	}
   156  	return ret
   157  }
   158  
   159  func mergeSubTreeByRank(bucket []*node, ptr *node /*ptr 是根节点*/) {
   160  	for bucket[ptr.rank] != nil {
   161  		rank := ptr.rank
   162  		ptr = link(ptr, bucket[rank])
   163  		bucket[rank] = nil
   164  	}
   165  	bucket[ptr.rank] = ptr
   166  }
   167  
   168  func link(a *node, b *node) *node {
   169  	// 前置条件是a、b都非空
   170  	var winner, loser *node
   171  	// 以a、b中较小的根作为合并后的半树的根
   172  	if a.item < b.item {
   173  		winner = a
   174  		loser = b
   175  	} else {
   176  		winner = b
   177  		loser = a
   178  	}
   179  
   180  	// 将胜出半树的左child挂到胜败半树的右child上(此前右child为空)
   181  	loser.next = winner.left
   182  	winner.left = loser
   183  	// 在此之前a、b的rank已经保证相等
   184  	winner.rank++
   185  	return winner
   186  }
   187  
   188  func (h *Heap) maxBucketSize() int {
   189  	// 对于一n个元素的rpheap,rank最多是log n
   190  	// 对于type 1或type 2的rpheap,rank上限更低,这里简单起见按log n算
   191  	bit, cnt := 0, h.size
   192  	for cnt > 1 {
   193  		cnt /= 2
   194  		bit++
   195  	}
   196  	return bit + 1 // [0, rank]共有rank+1个值
   197  }
   198  
   199  // Size of the heap
   200  func (h *Heap) Size() int {
   201  	return h.size
   202  }
   203  
   204  // Clear the heap
   205  func (h *Heap) Clear() {
   206  	h.head = nil
   207  	h.size = 0
   208  }