github.com/igggame/nebulas-go@v2.1.0+incompatible/common/pdeque/pdeque.go (about)

     1  package pdeque
     2  
     3  import (
     4  	"math"
     5  	"sync"
     6  )
     7  
     8  // Less is compare function for elements in queue
     9  type Less func(a interface{}, b interface{}) bool
    10  
    11  // PriorityDeque is a priority double-ended queue
    12  type PriorityDeque struct {
    13  	less Less
    14  	heap []interface{}
    15  	mu   sync.Mutex
    16  }
    17  
    18  // LvTy is type of level
    19  type LvTy int
    20  
    21  // LvMin & LvMax in priority double-ended queue
    22  const (
    23  	LvMin LvTy = iota
    24  	LvMax
    25  )
    26  
    27  // NewPriorityDeque create a new PriorityDeque
    28  func NewPriorityDeque(less Less) *PriorityDeque {
    29  	return &PriorityDeque{
    30  		less: less,
    31  	}
    32  }
    33  
    34  // Len return the length of the priority deque
    35  func (q *PriorityDeque) Len() int {
    36  	return len(q.heap)
    37  }
    38  
    39  // Insert an item into priority deque
    40  func (q *PriorityDeque) Insert(ele interface{}) {
    41  	q.mu.Lock()
    42  	defer q.mu.Unlock()
    43  
    44  	q.heap = append(q.heap, ele)
    45  	q.bubbleUp(q.Len() - 1)
    46  }
    47  
    48  // Max return the max value in priority deque
    49  func (q *PriorityDeque) Max() interface{} {
    50  	q.mu.Lock()
    51  	defer q.mu.Unlock()
    52  
    53  	heap := q.heap
    54  	pos := 0
    55  	switch q.Len() {
    56  	case 0:
    57  		return nil
    58  	case 1:
    59  		break
    60  	case 2:
    61  		pos = 1
    62  		break
    63  	default:
    64  		pos = 1
    65  		if q.less(heap[1], heap[2]) {
    66  			pos = 2
    67  		}
    68  		break
    69  	}
    70  	tx := heap[pos]
    71  	return tx
    72  }
    73  
    74  // PopMax pop the max value in priority deque
    75  func (q *PriorityDeque) PopMax() interface{} {
    76  	q.mu.Lock()
    77  	defer q.mu.Unlock()
    78  
    79  	heap := q.heap
    80  	pos := 0
    81  	switch q.Len() {
    82  	case 0:
    83  		return nil
    84  	case 1:
    85  		break
    86  	case 2:
    87  		pos = 1
    88  		break
    89  	default:
    90  		pos = 1
    91  		if q.less(heap[1], heap[2]) {
    92  			pos = 2
    93  		}
    94  		break
    95  	}
    96  	tx := heap[pos]
    97  	q.deleteAt(pos)
    98  	return tx
    99  }
   100  
   101  // PopMin pop the min value in priority deque
   102  func (q *PriorityDeque) PopMin() interface{} {
   103  	q.mu.Lock()
   104  	defer q.mu.Unlock()
   105  
   106  	if q.Len() > 0 {
   107  		tx := q.heap[0]
   108  		q.deleteAt(0)
   109  		return tx
   110  	}
   111  	return nil
   112  }
   113  
   114  // Min return the min value in priority deque
   115  func (q *PriorityDeque) Min() interface{} {
   116  	q.mu.Lock()
   117  	defer q.mu.Unlock()
   118  
   119  	if q.Len() > 0 {
   120  		tx := q.heap[0]
   121  		return tx
   122  	}
   123  	return nil
   124  }
   125  
   126  func (q *PriorityDeque) deleteAt(pos int) {
   127  	heap := q.heap
   128  	size := len(heap)
   129  	heap[pos] = heap[size-1]
   130  	q.heap = heap[0 : size-1]
   131  	q.trickleDown(pos)
   132  }
   133  
   134  func level(pos int) LvTy {
   135  	level := (int)(math.Floor(math.Log2((float64)(pos + 1))))
   136  	if level%2 == 0 {
   137  		return LvMin
   138  	}
   139  	return LvMax
   140  }
   141  
   142  func parent(pos int) int {
   143  	return (pos - 1) / 2
   144  }
   145  
   146  func leftChildren(pos int) int {
   147  	return pos*2 + 1
   148  }
   149  
   150  func rightChildren(pos int) int {
   151  	return pos*2 + 2
   152  }
   153  
   154  func (q *PriorityDeque) swap(i int, j int) {
   155  	q.heap[i], q.heap[j] = q.heap[j], q.heap[i]
   156  }
   157  
   158  func (q *PriorityDeque) bubbleUp(pos int) {
   159  	heap := q.heap
   160  	switch level(pos) {
   161  	case LvMin:
   162  		if pos > 0 {
   163  			if q.less(heap[parent(pos)], heap[pos]) {
   164  				q.swap(pos, parent(pos))
   165  				q.bubbleUpMax(parent(pos))
   166  			} else {
   167  				q.bubbleUpMin(pos)
   168  			}
   169  		}
   170  		break
   171  	case LvMax:
   172  		if pos > 0 {
   173  			if q.less(heap[pos], heap[parent(pos)]) {
   174  				q.swap(pos, parent(pos))
   175  				q.bubbleUpMin(parent(pos))
   176  			} else {
   177  				q.bubbleUpMax(pos)
   178  			}
   179  		}
   180  		break
   181  	}
   182  }
   183  
   184  func (q *PriorityDeque) bubbleUpMin(pos int) {
   185  	heap := q.heap
   186  	grandParent := parent(parent(pos))
   187  	if pos > 2 {
   188  		if q.less(heap[pos], heap[grandParent]) {
   189  			q.swap(pos, grandParent)
   190  			q.bubbleUpMin(grandParent)
   191  		}
   192  	}
   193  }
   194  
   195  func (q *PriorityDeque) bubbleUpMax(pos int) {
   196  	heap := q.heap
   197  	grandParent := parent(parent(pos))
   198  	if pos > 2 {
   199  		if q.less(heap[grandParent], heap[pos]) {
   200  			q.swap(pos, grandParent)
   201  			q.bubbleUpMax(grandParent)
   202  		}
   203  	}
   204  }
   205  
   206  func (q *PriorityDeque) trickleDown(pos int) {
   207  	switch level(pos) {
   208  	case LvMin:
   209  		q.trickleDownMin(pos)
   210  		break
   211  	case LvMax:
   212  		q.trickleDownMax(pos)
   213  		break
   214  	}
   215  }
   216  
   217  func (q *PriorityDeque) children(parents []int) []int {
   218  	heap := q.heap
   219  	size := len(heap)
   220  	res := []int{}
   221  	for _, pos := range parents {
   222  		if leftChildren(pos) < size {
   223  			res = append(res, leftChildren(pos))
   224  		}
   225  		if rightChildren(pos) < size {
   226  			res = append(res, rightChildren(pos))
   227  		}
   228  	}
   229  	return res
   230  }
   231  
   232  func (q *PriorityDeque) sort(items []int) []int {
   233  	heap := q.heap
   234  	for i := 0; i < len(items); i++ {
   235  		for j := i + 1; j < len(items); j++ {
   236  			if q.less(heap[items[j]], heap[items[i]]) {
   237  				items[i], items[j] = items[j], items[i]
   238  			}
   239  		}
   240  	}
   241  	return items
   242  }
   243  
   244  func (q *PriorityDeque) trickleDownMin(pos int) {
   245  	heap := q.heap
   246  	children := q.children([]int{pos})
   247  	if len(children) > 0 {
   248  		grandchild := q.children(children)
   249  		if len(grandchild) > 0 {
   250  			children = append(children, grandchild...)
   251  			opts := q.sort(children)
   252  			opt := opts[0]
   253  			if q.less(heap[opt], heap[pos]) {
   254  				q.swap(opt, pos)
   255  				if q.less(heap[parent(opt)], heap[pos]) {
   256  					q.swap(opt, parent(opt))
   257  				}
   258  				q.trickleDownMin(opt)
   259  			}
   260  		} else {
   261  			opts := q.sort(children)
   262  			opt := opts[0]
   263  			if q.less(heap[opt], heap[pos]) {
   264  				q.swap(opt, pos)
   265  			}
   266  		}
   267  	}
   268  }
   269  
   270  func (q *PriorityDeque) trickleDownMax(pos int) {
   271  	heap := q.heap
   272  	children := q.children([]int{pos})
   273  	if len(children) > 0 {
   274  		grandchild := q.children(children)
   275  		if len(grandchild) > 0 {
   276  			children = append(children, grandchild...)
   277  			opts := q.sort(children)
   278  			opt := opts[len(opts)-1]
   279  			if q.less(heap[pos], heap[opt]) {
   280  				q.swap(opt, pos)
   281  				if q.less(heap[opt], heap[parent(opt)]) {
   282  					q.swap(opt, parent(opt))
   283  				}
   284  				q.trickleDownMax(opt)
   285  			}
   286  		} else {
   287  			opts := q.sort(children)
   288  			opt := opts[len(opts)-1]
   289  			if q.less(heap[pos], heap[opt]) {
   290  				q.swap(opt, pos)
   291  			}
   292  		}
   293  	}
   294  }