Skip to content

Commit

Permalink
Add Peek method and more tests for queue and stack
Browse files Browse the repository at this point in the history
  • Loading branch information
Anwar Ziani committed Feb 10, 2020
1 parent 06d16a9 commit 91f2ad0
Show file tree
Hide file tree
Showing 4 changed files with 135 additions and 17 deletions.
60 changes: 52 additions & 8 deletions queue/queue.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,36 +2,80 @@ package queue

import (
"sync"

list "github.com/zianwar/datastructures/linkedlist/single"
)

// Queue represents a thread-safe queue data structure
type Queue struct {
sync.Mutex
items []int
l *list.List
size int
}

// NewQueue returns a new queue
func NewQueue() *Queue {
return &Queue{
items: make([]int, 0),
l: list.NewList(),
}
}

func (q *Queue) Enqueue(v int) {
// Size returns the size of the queue
// O(1)
func (q *Queue) Size() int {
q.Lock()
defer q.Unlock()

q.items = append(q.items, v)
return q.size
}

func (q *Queue) Dequeue() (int, bool) {
// Peek returns the item at the front of the queue
// O(1)
func (q *Queue) Peek() interface{} {
q.Lock()
defer q.Unlock()

if len(q.items) > 0 {
v := q.items[0]
q.items = q.items[0:]
if q.size == 0 {
return nil
}
return q.l.Tail().Value
}

// Enqueue adds an item to the back of the queue
// O(1)
func (q *Queue) Enqueue(v interface{}) {
q.Lock()
defer q.Unlock()

q.l.Append(v)
q.size++
}

// Dequeue deletes and returns the item at front of the queue
// O(1)
func (q *Queue) Dequeue() (interface{}, bool) {
q.Lock()
defer q.Unlock()

if q.size > 0 {
n := q.l.Front()
v := n.Value
if ok := q.l.Remove(n); !ok {
return 0, false
}
q.size--
return v, true
}

// Queue is empty
return 0, false
}

// ToArray returns an array representation of the stack
// O(N)
func (q *Queue) ToArray() []interface{} {
q.Lock()
defer q.Unlock()

return q.l.ToArray()
}
52 changes: 48 additions & 4 deletions queue/queue_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,59 @@ package queue

import "testing"

func TestQueue(t *testing.T) {
func TestEnqueue(t *testing.T) {
q := NewQueue()
q.Enqueue(1)
q.Enqueue(2)

got, _ := q.Dequeue()
expected := 1
expected := []interface{}{1, 2}
got := q.ToArray()
if !Equal(got, expected) {
t.Errorf("expected %v got %v", expected, got)
}
}

func TestPeek(t *testing.T) {
q := NewQueue()
q.Enqueue(1)
q.Enqueue(2)
q.Dequeue()
v := q.Peek()

expected := 2
got := v
if got != expected {
t.Errorf("expected %v got %v", expected, got)
}
}

func TestDequeue(t *testing.T) {
q := NewQueue()
q.Enqueue(1)
q.Enqueue(2)
v, ok := q.Dequeue()

if !ok {
t.Error("operation failed")
}

expected := 1
got := v
if got != expected {
t.Errorf("got %v expected %v", got, expected)
t.Errorf("expected %v got %v", expected, got)
}
}

// Equal tells whether a and b contain the same elements.
// A nil argument is equivalent to an empty slice.
func Equal(a, b []interface{}) bool {
if len(a) != len(b) {
return false
}
for i, v := range a {
if v != b[i] {
return false
}
}
return true
}
17 changes: 14 additions & 3 deletions stack/stack.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,18 @@ import (
list "github.com/zianwar/datastructures/linkedlist/single"
)

// Stack represents a thread-safe stack
// Stack represents a thread-safe stack data structure
type Stack struct {
sync.Mutex
l list.List
l *list.List
size int
}

// NewStack returns new stack
func NewStack() *Stack {
return &Stack{}
return &Stack{
l: list.NewList(),
}
}

// Size returns the size of the stack
Expand All @@ -24,6 +26,15 @@ func (s *Stack) Size() int {
return s.size
}

// Peek returns the item at the top of the stack
// O(1)
func (s *Stack) Peek() interface{} {
if s.size == 0 {
return nil
}
return s.l.Front().Value
}

// Push pushes an element into the stack
// O(1)
func (s *Stack) Push(v interface{}) {
Expand Down
23 changes: 21 additions & 2 deletions stack/stack_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,32 @@ func TestPop(t *testing.T) {
t.Error("operation failed")
}

expected := v
got := 1
expected := 1
got := v
if got != expected {
t.Errorf("expected %v got %v", expected, got)
}
}

func TestPeek(t *testing.T) {
s := NewStack()
s.Push(1)
s.Push(2)
v := s.Peek()

expected := 2
got := v
if got != expected {
t.Errorf("expected %v got %v", expected, got)
}

expected2 := []interface{}{2, 1}
got2 := s.ToArray()
if !Equal(got2, expected2) {
t.Errorf("expected %v got %v", expected2, got2)
}
}

// Equal tells whether a and b contain the same elements.
// A nil argument is equivalent to an empty slice.
func Equal(a, b []interface{}) bool {
Expand Down

0 comments on commit 91f2ad0

Please sign in to comment.