From 991a1227b7450d56b5d713cfe2ebcb7736f8ce42 Mon Sep 17 00:00:00 2001 From: 0xAX Date: Sat, 9 Aug 2014 23:24:50 +0600 Subject: [PATCH] doubly linked list added --- README.md | 6 +- collections/list/list.go | 119 ++++++++++++++++++++++++++++++++++ collections/list/list_test.go | 33 ++++++++++ 3 files changed, 155 insertions(+), 3 deletions(-) create mode 100644 collections/list/list.go create mode 100644 collections/list/list_test.go diff --git a/README.md b/README.md index 9e5e4fd..36b412a 100644 --- a/README.md +++ b/README.md @@ -29,10 +29,10 @@ alghoritms * Shell sort * counting sort -#### Searching +#### Collections -#### Data structures - + * doubly linked list + contribution ------------ diff --git a/collections/list/list.go b/collections/list/list.go new file mode 100644 index 0000000..edffba3 --- /dev/null +++ b/collections/list/list.go @@ -0,0 +1,119 @@ +package collections + +import "sync" + +type List struct { + head *Item + last *Item + len int + locker sync.RWMutex +} + +type Item struct { + Val interface{} + next *Item + prev *Item + list *List +} + +func New() *List { + list := &List{} + list.len = 0 + return list +} + +func Insert(value interface{}, list *List) *List { + newItem := &Item{value, list.head, list.last, list} + list.locker.Lock() + defer list.locker.Unlock() + + if list.head == nil { + list.head = newItem + list.last = newItem + } else { + list.head = newItem + list.head.prev = newItem + list.last.next = newItem + } + + list.len++ + + return list +} + +func (list *List) First() *Item { + return list.head +} + +func (list *List) Last() *Item { + return list.last +} + +func (item *Item) Prev() *Item { + return item.prev +} + +func (item *Item) Next() *Item { + return item.next +} + +func Has(value interface{}, list *List) bool { + if list.head == nil{ + return false + } + first := list.First() + + for { + if first.Val == value { + return true + } else { + if first.next != nil { + first = first.next + } else { + return false + } + } + } + + return false +} + +func Remove(value interface{}, list *List) *List { + list.locker.RLock() + + if list.head == nil { + return list + } + + list.locker.RUnlock() + + list.locker.RLock() + first := list.First() + last := list.Last() + list.locker.RUnlock() + list.locker.Lock() + defer list.locker.Unlock() + + for { + if last.next == nil { + return list + } + + if first.Val == value { + first.prev.next = first.next + first.next.prev = first.prev + first.prev = nil + first.next = nil + first.Val = nil + first.list = nil + list.len-- + return list + } else { + first = first.next + } + } +} + +func Length(list *List) int { + return list.len +} diff --git a/collections/list/list_test.go b/collections/list/list_test.go new file mode 100644 index 0000000..27d92fd --- /dev/null +++ b/collections/list/list_test.go @@ -0,0 +1,33 @@ +package list + +import "testing" + +func Test_New(t *testing.T) { + list := New() + list = Insert(1, list) + list = Insert(2, list) + list = Insert(3, list) + list = Insert(10, list) + list = Insert(103, list) + list = Insert(56, list) + + has := Has(103, list) + if has != true { + t.Error("[Error] Has(103, list) doesn't work as expected'") + } + + if Length(list) != 6 { + t.Error("[Error] Length(list) doensn't work as expected'") + } + + list = Remove(10, list) + + has = Has(10, list) + if has != false { + t.Error("[Error] Has(10, list) doesn't work as expected after removing 10 from list'") + } + + if Length(list) != 5 { + t.Error("[Error] Length(list) doensn't work as expected after removing data from list'") + } +}