github.com/linapex/ethereum-go-chinese@v0.0.0-20190316121929-f8b7a73c3fa1/common/prque/sstack.go (about)

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