diff options
Diffstat (limited to 'libgo/go/container/list/list.go')
-rwxr-xr-x | libgo/go/container/list/list.go | 211 |
1 files changed, 211 insertions, 0 deletions
diff --git a/libgo/go/container/list/list.go b/libgo/go/container/list/list.go new file mode 100755 index 000000000..c1ebcddaa --- /dev/null +++ b/libgo/go/container/list/list.go @@ -0,0 +1,211 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// The list package implements a doubly linked list. +// +// To iterate over a list (where l is a *List): +// for e := l.Front(); e != nil; e = e.Next() { +// // do something with e.Value +// } +// +package list + +// Element is an element in the linked list. +type Element struct { + // Next and previous pointers in the doubly-linked list of elements. + // The front of the list has prev = nil, and the back has next = nil. + next, prev *Element + + // The list to which this element belongs. + list *List + + // The contents of this list element. + Value interface{} +} + +// Next returns the next list element or nil. +func (e *Element) Next() *Element { return e.next } + +// Prev returns the previous list element or nil. +func (e *Element) Prev() *Element { return e.prev } + +// List represents a doubly linked list. +// The zero value for List is an empty list ready to use. +type List struct { + front, back *Element + len int +} + +// Init initializes or clears a List. +func (l *List) Init() *List { + l.front = nil + l.back = nil + l.len = 0 + return l +} + +// New returns an initialized list. +func New() *List { return new(List) } + +// Front returns the first element in the list. +func (l *List) Front() *Element { return l.front } + +// Back returns the last element in the list. +func (l *List) Back() *Element { return l.back } + +// Remove removes the element from the list +// and returns its Value. +func (l *List) Remove(e *Element) interface{} { + l.remove(e) + e.list = nil // do what remove does not + return e.Value +} + +// remove the element from the list, but do not clear the Element's list field. +// This is so that other List methods may use remove when relocating Elements +// without needing to restore the list field. +func (l *List) remove(e *Element) { + if e.list != l { + return + } + if e.prev == nil { + l.front = e.next + } else { + e.prev.next = e.next + } + if e.next == nil { + l.back = e.prev + } else { + e.next.prev = e.prev + } + + e.prev = nil + e.next = nil + l.len-- +} + +func (l *List) insertBefore(e *Element, mark *Element) { + if mark.prev == nil { + // new front of the list + l.front = e + } else { + mark.prev.next = e + } + e.prev = mark.prev + mark.prev = e + e.next = mark + l.len++ +} + +func (l *List) insertAfter(e *Element, mark *Element) { + if mark.next == nil { + // new back of the list + l.back = e + } else { + mark.next.prev = e + } + e.next = mark.next + mark.next = e + e.prev = mark + l.len++ +} + +func (l *List) insertFront(e *Element) { + if l.front == nil { + // empty list + l.front, l.back = e, e + e.prev, e.next = nil, nil + l.len = 1 + return + } + l.insertBefore(e, l.front) +} + +func (l *List) insertBack(e *Element) { + if l.back == nil { + // empty list + l.front, l.back = e, e + e.prev, e.next = nil, nil + l.len = 1 + return + } + l.insertAfter(e, l.back) +} + +// PushFront inserts the value at the front of the list and returns a new Element containing the value. +func (l *List) PushFront(value interface{}) *Element { + e := &Element{nil, nil, l, value} + l.insertFront(e) + return e +} + +// PushBack inserts the value at the back of the list and returns a new Element containing the value. +func (l *List) PushBack(value interface{}) *Element { + e := &Element{nil, nil, l, value} + l.insertBack(e) + return e +} + +// InsertBefore inserts the value immediately before mark and returns a new Element containing the value. +func (l *List) InsertBefore(value interface{}, mark *Element) *Element { + if mark.list != l { + return nil + } + e := &Element{nil, nil, l, value} + l.insertBefore(e, mark) + return e +} + +// InsertAfter inserts the value immediately after mark and returns a new Element containing the value. +func (l *List) InsertAfter(value interface{}, mark *Element) *Element { + if mark.list != l { + return nil + } + e := &Element{nil, nil, l, value} + l.insertAfter(e, mark) + return e +} + +// MoveToFront moves the element to the front of the list. +func (l *List) MoveToFront(e *Element) { + if e.list != l || l.front == e { + return + } + l.remove(e) + l.insertFront(e) +} + +// MoveToBack moves the element to the back of the list. +func (l *List) MoveToBack(e *Element) { + if e.list != l || l.back == e { + return + } + l.remove(e) + l.insertBack(e) +} + +// Len returns the number of elements in the list. +func (l *List) Len() int { return l.len } + +// PushBackList inserts each element of ol at the back of the list. +func (l *List) PushBackList(ol *List) { + last := ol.Back() + for e := ol.Front(); e != nil; e = e.Next() { + l.PushBack(e.Value) + if e == last { + break + } + } +} + +// PushFrontList inserts each element of ol at the front of the list. The ordering of the passed list is preserved. +func (l *List) PushFrontList(ol *List) { + first := ol.Front() + for e := ol.Back(); e != nil; e = e.Prev() { + l.PushFront(e.Value) + if e == first { + break + } + } +} |