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