Skip to content

Commit

Permalink
Solve the "Implement a circular queue" problem
Browse files Browse the repository at this point in the history
  • Loading branch information
mrekucci committed Oct 16, 2015
1 parent 2da37da commit ba251df
Show file tree
Hide file tree
Showing 7 changed files with 215 additions and 85 deletions.
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ Stacks and Queues
| Problem | Test | Implemented |
|--------------------------------------------------------------------------|:------------:|:-----------:|
| [Compute binary tree nodes in order of increasing depth][136] | [tests][137] | |
| [Implement a circular queue][138] | [tests][139] | |
| [Implement a circular queue][138] | [tests][139] | |
| [Implement a queue using stacks][140] | [tests][141] | |
| [Implement a queue with max API][142] | [tests][143] | |

Expand Down Expand Up @@ -534,8 +534,8 @@ Honors Class
[135]: in_progress.md
[136]: in_progress.md
[137]: in_progress.md
[138]: in_progress.md
[139]: in_progress.md
[138]: queues/circqueue.go
[139]: queues/circqueue_test.go
[140]: in_progress.md
[141]: in_progress.md
[142]: in_progress.md
Expand Down
62 changes: 62 additions & 0 deletions queues/circqueue.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
// Copyright (c) 2015, Peter Mrekaj. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE.txt file.

package queues

// IntArrayQueue is an implementation of the Queue interface
// for integer values implemented by array.
type IntArrayQueue struct {
head, tail int
len int
an []int
}

// Enqueue inserts e element at the back of the queue.
// An error is returned if e is not of type int.
// The time complexity is O(1) amortized.
func (q *IntArrayQueue) Enqueue(e interface{}) error {
v, ok := e.(int)
if !ok {
return ErrType
}
if q.Len() == cap(q.an) { // Resize.
an := make([]int, 2*cap(q.an))
n := copy(an, q.an[q.head:])
copy(an[n:], q.an[:q.tail])
q.head = 0
q.tail = q.Len()
q.an = an
}
q.an[q.tail] = v
q.tail = (q.tail + 1) % cap(q.an)
q.len++
return nil
}

// Dequeue removes and returns the front integer element from this queue.
// The time complexity is O(1)
func (q *IntArrayQueue) Dequeue() interface{} {
if q.Len() == 0 {
return nil
}
e := q.an[q.head]
q.head = (q.head + 1) % cap(q.an)
q.len--
return e
}

// Len returns the length of this queue.
// The time complexity is O(1)
func (q *IntArrayQueue) Len() int {
return q.len
}

// NewIntArrayQueue returns a new *IntArrayQueue with given size.
// The size is set automatically to 2 if given size is less then 2.
func NewIntArrayQueue(size int) *IntArrayQueue {
if size < 2 {
size = 2
}
return &IntArrayQueue{an: make([]int, size)}
}
42 changes: 42 additions & 0 deletions queues/circqueue_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
// Copyright (c) 2015, Peter Mrekaj. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE.txt file.

package queues

import "testing"

func TestIntArrayQueue(t *testing.T) {
ifaceTests := []queueTest{
{0, nil},
{1, nil},
{2, nil},
{3, nil},
{4, nil},
{5, nil},
{6, nil},
{7, nil},
{8, nil},
{9, nil},
{minInt, nil},
{maxInt, nil},
{"x", ErrType},
}
if err := testQueueInterface(t, NewIntArrayQueue(0), ifaceTests); err != nil {
t.Error(err)
}
}

func BenchmarkIntArrayQueue(b *testing.B) {
b.StopTimer()
q := NewIntArrayQueue(0)
b.StartTimer()
for i := 0; i < b.N; i++ {
q.Enqueue(i)
if i%64 == 0 {
for i := 0; i < 16; i++ {
q.Dequeue()
}
}
}
}
66 changes: 66 additions & 0 deletions queues/listqueue.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
// Copyright (c) 2015, Peter Mrekaj. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE.txt file.

package queues

type node struct {
data int
next *node
}

// IntListQueue is an implementation of the Queue interface
// for integer values implemented by circular linked list.
type IntListQueue struct {
head, tail *node
len int
}

// Enqueue inserts e element at the back of the queue.
// An error is returned if e is not of type int.
// The time complexity is O(1)
func (q *IntListQueue) Enqueue(e interface{}) error {
v, ok := e.(int)
if !ok {
return ErrType
}
n := &node{data: v}
if q.head == nil {
q.head = n
n.next = q.head
q.tail = q.head
} else {
q.tail.next = n
n.next = q.head
q.tail = n
}
q.len++
return nil
}

// Dequeue removes and returns the front integer element from this queue.
// The time complexity is O(1)
func (q *IntListQueue) Dequeue() interface{} {
switch q.len {
case 0:
return nil
case 1:
v := q.head.data
q.head = nil
q.tail = nil
q.len = 0
return v
}
n := q.head
q.head = n.next
q.tail.next = q.head
n.next = nil // Avoid memory leaks.
q.len--
return n.data
}

// Len returns the length of this queue.
// The time complexity is O(1)
func (q *IntListQueue) Len() int {
return q.len
}
42 changes: 42 additions & 0 deletions queues/listqueue_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
// Copyright (c) 2015, Peter Mrekaj. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE.txt file.

package queues

import "testing"

func TestIntListQueue(t *testing.T) {
ifaceTests := []queueTest{
{0, nil},
{1, nil},
{2, nil},
{3, nil},
{4, nil},
{5, nil},
{6, nil},
{7, nil},
{8, nil},
{9, nil},
{minInt, nil},
{maxInt, nil},
{"x", ErrType},
}
if err := testQueueInterface(t, new(IntListQueue), ifaceTests); err != nil {
t.Error(err)
}
}

func BenchmarkIntListQueue(b *testing.B) {
b.StopTimer()
q := new(IntListQueue)
b.StartTimer()
for i := 0; i < b.N; i++ {
q.Enqueue(i)
if i%64 == 0 {
for i := 0; i < 16; i++ {
q.Dequeue()
}
}
}
}
61 changes: 0 additions & 61 deletions queues/queue.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,64 +21,3 @@ type Queue interface {
// Length of the queue.
Len() int
}

type node struct {
data int
next *node
}

// IntListQueue is an implementation of the Queue interface
// for integer values implemented by circular linked list.
type IntListQueue struct {
head, tail *node
len int
}

// Enqueue inserts e element at the back of the queue.
// An error is returned if e is not of type int.
// The time complexity is O(1)
func (q *IntListQueue) Enqueue(e interface{}) error {
v, ok := e.(int)
if !ok {
return ErrType
}
n := &node{data: v}
if q.head == nil {
q.head = n
n.next = q.head
q.tail = q.head
} else {
q.tail.next = n
n.next = q.head
q.tail = n
}
q.len++
return nil
}

// Dequeue removes and returns the front integer element from this queue.
// The time complexity is O(1)
func (q *IntListQueue) Dequeue() interface{} {
switch q.len {
case 0:
return nil
case 1:
v := q.head.data
q.head = nil
q.tail = nil
q.len = 0
return v
}
n := q.head
q.head = n.next
q.tail.next = q.head
n.next = nil // Avoid memory leaks.
q.len--
return n.data
}

// Len returns the length of this queue.
// The time complexity is O(1)
func (q *IntListQueue) Len() int {
return q.len
}
21 changes: 0 additions & 21 deletions queues/queue_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,24 +69,3 @@ type queueTest struct {
e interface{}
err error
}

func TestIntListQueue(t *testing.T) {
ifaceTests := []queueTest{
{0, nil},
{1, nil},
{2, nil},
{3, nil},
{4, nil},
{5, nil},
{6, nil},
{7, nil},
{8, nil},
{9, nil},
{minInt, nil},
{maxInt, nil},
{"x", ErrType},
}
if err := testQueueInterface(t, new(IntListQueue), ifaceTests); err != nil {
t.Error(err)
}
}

0 comments on commit ba251df

Please sign in to comment.