github.com/mailgun/holster/v4@v4.20.0/collections/priority_queue.go (about)

     1  /*
     2  Copyright 2017 Mailgun Technologies Inc
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8  	http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  package collections
    17  
    18  import (
    19  	"container/heap"
    20  )
    21  
    22  // An PQItem is something we manage in a priority queue.
    23  type PQItem struct {
    24  	Value    interface{}
    25  	Priority int // The priority of the item in the queue.
    26  	// The index is needed by update and is maintained by the heap.Interface methods.
    27  	index int // The index of the item in the heap.
    28  }
    29  
    30  // Implements a PriorityQueue
    31  type PriorityQueue struct {
    32  	impl *pqImpl
    33  }
    34  
    35  func NewPriorityQueue() *PriorityQueue {
    36  	mh := &pqImpl{}
    37  	heap.Init(mh)
    38  	return &PriorityQueue{impl: mh}
    39  }
    40  
    41  func (p PriorityQueue) Len() int { return p.impl.Len() }
    42  
    43  func (p *PriorityQueue) Push(el *PQItem) {
    44  	heap.Push(p.impl, el)
    45  }
    46  
    47  func (p *PriorityQueue) Pop() *PQItem {
    48  	el := heap.Pop(p.impl)
    49  	return el.(*PQItem)
    50  }
    51  
    52  func (p *PriorityQueue) Peek() *PQItem {
    53  	return (*p.impl)[0]
    54  }
    55  
    56  // Modifies the priority and value of an Item in the queue.
    57  func (p *PriorityQueue) Update(el *PQItem, priority int) {
    58  	heap.Remove(p.impl, el.index)
    59  	el.Priority = priority
    60  	heap.Push(p.impl, el)
    61  }
    62  
    63  func (p *PriorityQueue) Remove(el *PQItem) {
    64  	heap.Remove(p.impl, el.index)
    65  }
    66  
    67  // Actual Implementation using heap.Interface
    68  type pqImpl []*PQItem
    69  
    70  func (mh pqImpl) Len() int { return len(mh) }
    71  
    72  func (mh pqImpl) Less(i, j int) bool {
    73  	return mh[i].Priority < mh[j].Priority
    74  }
    75  
    76  func (mh pqImpl) Swap(i, j int) {
    77  	mh[i], mh[j] = mh[j], mh[i]
    78  	mh[i].index = i
    79  	mh[j].index = j
    80  }
    81  
    82  func (mh *pqImpl) Push(x interface{}) {
    83  	n := len(*mh)
    84  	item := x.(*PQItem)
    85  	item.index = n
    86  	*mh = append(*mh, item)
    87  }
    88  
    89  func (mh *pqImpl) Pop() interface{} {
    90  	old := *mh
    91  	n := len(old)
    92  	item := old[n-1]
    93  	item.index = -1 // for safety
    94  	*mh = old[0 : n-1]
    95  	return item
    96  }