github.com/yinchengtsinghua/golang-Eos-dpos-Ethereum@v0.0.0-20190121132951-92cc4225ed8e/common/prque/sstack.go (about)

     1  
     2  //此源码被清华学神尹成大魔王专业翻译分析并修改
     3  //尹成QQ77025077
     4  //尹成微信18510341407
     5  //尹成所在QQ群721929980
     6  //尹成邮箱 yinc13@mails.tsinghua.edu.cn
     7  //尹成毕业于清华大学,微软区块链领域全球最有价值专家
     8  //https://mvp.microsoft.com/zh-cn/PublicProfile/4033620
     9  //这是“gopkg.in/karalabe/cookiejar.v2/collections/prque”的一个复制和稍加修改的版本。
    10  
    11  package prque
    12  
    13  //数据块的大小
    14  const blockSize = 4096
    15  
    16  //排序堆栈中的优先项。
    17  //
    18  //注意:优先级可以“环绕”Int64范围,如果(a.priority-b.priority)>0,则A在B之前。
    19  //队列中任何点的最低优先级和最高优先级之间的差异应小于2^63。
    20  type item struct {
    21  	value    interface{}
    22  	priority int64
    23  }
    24  
    25  //将元素移动到新索引时调用setindexcallback。
    26  //提供setindexcallback是可选的,只有在应用程序需要时才需要它
    27  //删除顶部元素以外的元素。
    28  type setIndexCallback func(a interface{}, i int)
    29  
    30  //内部可排序堆栈数据结构。为执行推送和弹出操作
    31  //堆栈(堆)功能和len、less和swap方法
    32  //堆的可分类性要求。
    33  type sstack struct {
    34  	setIndex setIndexCallback
    35  	size     int
    36  	capacity int
    37  	offset   int
    38  
    39  	blocks [][]*item
    40  	active []*item
    41  }
    42  
    43  //创建新的空堆栈。
    44  func newSstack(setIndex setIndexCallback) *sstack {
    45  	result := new(sstack)
    46  	result.setIndex = setIndex
    47  	result.active = make([]*item, blockSize)
    48  	result.blocks = [][]*item{result.active}
    49  	result.capacity = blockSize
    50  	return result
    51  }
    52  
    53  //将值推送到堆栈上,必要时将其展开。要求
    54  //HEAP.接口
    55  func (s *sstack) Push(data interface{}) {
    56  	if s.size == s.capacity {
    57  		s.active = make([]*item, blockSize)
    58  		s.blocks = append(s.blocks, s.active)
    59  		s.capacity += blockSize
    60  		s.offset = 0
    61  	} else if s.offset == blockSize {
    62  		s.active = s.blocks[s.size/blockSize]
    63  		s.offset = 0
    64  	}
    65  	if s.setIndex != nil {
    66  		s.setIndex(data.(*item).value, s.size)
    67  	}
    68  	s.active[s.offset] = data.(*item)
    69  	s.offset++
    70  	s.size++
    71  }
    72  
    73  //从堆栈中弹出一个值并返回它。目前还没有收缩。
    74  //heap.interface需要。
    75  func (s *sstack) Pop() (res interface{}) {
    76  	s.size--
    77  	s.offset--
    78  	if s.offset < 0 {
    79  		s.offset = blockSize - 1
    80  		s.active = s.blocks[s.size/blockSize]
    81  	}
    82  	res, s.active[s.offset] = s.active[s.offset], nil
    83  	if s.setIndex != nil {
    84  		s.setIndex(res.(*item).value, -1)
    85  	}
    86  	return
    87  }
    88  
    89  //返回堆栈的长度。sort.interface需要。
    90  func (s *sstack) Len() int {
    91  	return s.size
    92  }
    93  
    94  //比较堆栈中两个元素的优先级(较高的是第一个)。
    95  //sort.interface需要。
    96  func (s *sstack) Less(i, j int) bool {
    97  	return (s.blocks[i/blockSize][i%blockSize].priority - s.blocks[j/blockSize][j%blockSize].priority) > 0
    98  }
    99  
   100  //交换堆栈中的两个元素。sort.interface需要。
   101  func (s *sstack) Swap(i, j int) {
   102  	ib, io, jb, jo := i/blockSize, i%blockSize, j/blockSize, j%blockSize
   103  	a, b := s.blocks[jb][jo], s.blocks[ib][io]
   104  	if s.setIndex != nil {
   105  		s.setIndex(a.value, i)
   106  		s.setIndex(b.value, j)
   107  	}
   108  	s.blocks[ib][io], s.blocks[jb][jo] = a, b
   109  }
   110  
   111  //重置堆栈,有效地清除其内容。
   112  func (s *sstack) Reset() {
   113  	*s = *newSstack(s.setIndex)
   114  }