github.com/chain5j/chain5j-pkg@v1.0.7/collection/queues/preque/sstack.go (about)

     1  // CookieJar - A contestant's algorithm toolbox
     2  // Copyright (c) 2013 Peter Szilagyi. All rights reserved.
     3  //
     4  // CookieJar is dual licensed: use of this source code is governed by a BSD
     5  // license that can be found in the LICENSE file. Alternatively, the CookieJar
     6  // toolbox may be used in accordance with the terms and conditions contained
     7  // in a signed written agreement between you and the author(s).
     8  
     9  package prque
    10  
    11  // The size of a block of data
    12  const blockSize = 4096
    13  
    14  // A prioritized item in the sorted stack.
    15  type item struct {
    16  	value    interface{}
    17  	priority float32
    18  }
    19  
    20  // Internal sortable stack data structure. Implements the Push and Pop ops for
    21  // the stack (heap) functionality and the Len, Less and Swap methods for the
    22  // sortability requirements of the heaps.
    23  type sstack struct {
    24  	size     int
    25  	capacity int
    26  	offset   int
    27  
    28  	blocks [][]*item
    29  	active []*item
    30  }
    31  
    32  // Creates a new, empty stack.
    33  func newSstack() *sstack {
    34  	result := new(sstack)
    35  	result.active = make([]*item, blockSize)
    36  	result.blocks = [][]*item{result.active}
    37  	result.capacity = blockSize
    38  	return result
    39  }
    40  
    41  // Push a value onto the stack, expanding it if necessary. Required by
    42  // heap.Interface.
    43  func (s *sstack) Push(data interface{}) {
    44  	if s.size == s.capacity {
    45  		s.active = make([]*item, blockSize)
    46  		s.blocks = append(s.blocks, s.active)
    47  		s.capacity += blockSize
    48  		s.offset = 0
    49  	} else if s.offset == blockSize {
    50  		s.active = s.blocks[s.size/blockSize]
    51  		s.offset = 0
    52  	}
    53  	s.active[s.offset] = data.(*item)
    54  	s.offset++
    55  	s.size++
    56  }
    57  
    58  // Pop a value off the stack and returns it. Currently no shrinking is done.
    59  // Required by heap.Interface.
    60  func (s *sstack) Pop() (res interface{}) {
    61  	s.size--
    62  	s.offset--
    63  	if s.offset < 0 {
    64  		s.offset = blockSize - 1
    65  		s.active = s.blocks[s.size/blockSize]
    66  	}
    67  	res, s.active[s.offset] = s.active[s.offset], nil
    68  	return
    69  }
    70  func (s *sstack) PeekFront() (res interface{}) {
    71  	index := s.offset - 1
    72  	if index < 0 {
    73  		return nil
    74  	}
    75  	res = s.active[index]
    76  	return
    77  }
    78  
    79  func (s *sstack) Len() int {
    80  	return s.size
    81  }
    82  func (s *sstack) Less(i, j int) bool {
    83  	return s.blocks[i/blockSize][i%blockSize].priority > s.blocks[j/blockSize][j%blockSize].priority
    84  }
    85  func (s *sstack) Swap(i, j int) {
    86  	ib, io, jb, jo := i/blockSize, i%blockSize, j/blockSize, j%blockSize
    87  	s.blocks[ib][io], s.blocks[jb][jo] = s.blocks[jb][jo], s.blocks[ib][io]
    88  }
    89  func (s *sstack) Reset() {
    90  	*s = *newSstack()
    91  }