siddontang.golib/list/list.go

249 lines
3.7 KiB
Go

package list
const defaultSize = 1024
type Element struct {
Value interface{}
prev int
next int
index int
list *List
}
func (e *Element) Next() *Element {
if e.next == 0 || e.prev == -1 || e.list == nil {
return nil
}
return e.list.elems[e.next]
}
func (e *Element) Prev() *Element {
if e.prev == 0 || e.prev == -1 || e.list == nil {
return nil
}
return e.list.elems[e.prev]
}
//static linked list based array
type List struct {
elems []*Element
num int
root *Element
free int
}
func New() *List {
return NewSize(defaultSize)
}
func NewSize(size int) *List {
if size < defaultSize {
size = defaultSize
}
l := new(List)
l.elems = make([]*Element, size)
for i := range l.elems {
e := new(Element)
e.list = l
e.index = i
e.next = i + 1
if i+1 == len(l.elems) {
e.next = -1
}
l.elems[i] = e
}
//use first for root
l.root = l.elems[0]
l.root.next = 0
l.root.prev = 0
l.free = 1
l.num = 0
return l
}
func (l *List) Len() int {
return l.num
}
func (l *List) Front() *Element {
if l.root.next == 0 {
return nil
} else {
return l.elems[l.root.next]
}
}
func (l *List) Back() *Element {
if l.root.prev == 0 {
return nil
} else {
return l.elems[l.root.prev]
}
}
func (l *List) remove(e *Element) *Element {
next := e.next
prev := e.prev
l.elems[prev].next = next
l.elems[next].prev = prev
e.next = -1
e.prev = -1
l.num--
return e
}
func (l *List) Remove(e *Element) interface{} {
if e.list != l {
return nil
}
if e.prev == -1 {
return e.Value
}
l.remove(e)
v := e.Value
e.Value = nil
e.next = l.free
l.free = e.index
return v
}
func (l *List) getFreeElem() *Element {
if l.free == -1 {
//no free elements, create
num := len(l.elems)
newElems := make([]*Element, 2*num)
for i := num; i < 2*num; i++ {
e := new(Element)
e.list = l
e.index = i
e.next = i + 1
if i+1 == 2*num {
e.next = -1
}
newElems[i] = e
}
l.free = num
copy(newElems, l.elems)
l.elems = newElems
}
n := l.free
l.free = l.elems[n].next
return l.elems[n]
}
func (l *List) insert(e *Element, index int) *Element {
at := l.elems[index]
n := at.next
at.next = e.index
e.prev = at.index
e.next = n
l.elems[n].prev = e.index
e.list = l
l.num++
return e
}
func (l *List) insertValue(v interface{}, index int) *Element {
e := l.getFreeElem()
e.Value = v
return l.insert(e, index)
}
func (l *List) PushFront(v interface{}) *Element {
return l.insertValue(v, l.root.index)
}
func (l *List) PushBack(v interface{}) *Element {
return l.insertValue(v, l.root.prev)
}
func (l *List) InsertBefore(v interface{}, mark *Element) *Element {
if mark.list != l {
return nil
}
return l.insertValue(v, mark.prev)
}
func (l *List) InsertAfter(v interface{}, mark *Element) *Element {
if mark.list != l {
return nil
}
return l.insertValue(v, mark.index)
}
func (l *List) MoveToFront(e *Element) {
if e.list != l || l.root.next == e.index {
return
}
l.insert(l.remove(e), l.root.index)
}
func (l *List) MoveToBack(e *Element) {
if e.list != l || l.root.prev == e.index {
return
}
l.insert(l.remove(e), l.root.prev)
}
func (l *List) MoveBefore(e, mark *Element) {
if e.list != l || e == mark {
return
}
l.insert(l.remove(e), mark.prev)
}
func (l *List) MoveAfter(e, mark *Element) {
if e.list != l || e == mark {
return
}
l.insert(l.remove(e), mark.index)
}
func (l *List) PushBackList(other *List) {
for i, e := other.Len(), other.Front(); i > 0; i, e = i-1, e.Next() {
l.insertValue(e.Value, l.root.prev)
}
}
func (l *List) PushFrontList(other *List) {
for i, e := other.Len(), other.Back(); i > 0; i, e = i-1, e.Prev() {
l.insertValue(e.Value, l.root.index)
}
}