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 }