Skip to content

Commit

Permalink
add more details to queue
Browse files Browse the repository at this point in the history
  • Loading branch information
spring1843 committed Jul 4, 2024
1 parent 1909e89 commit 45da642
Show file tree
Hide file tree
Showing 2 changed files with 74 additions and 1 deletion.
12 changes: 11 additions & 1 deletion queue/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,17 @@ func dequeue() (int, error) {

## Complexity

Enqueue and dequeue operations both perform in O(1) times.
Enqueue and dequeue operations both perform in O(1) times in the linked list implementation. In other traditional languages like C the linked list approach is considered to be faster than the slice approach because both enqueue and dequeue operations are O(n) due to the slice size change. In Go however slices are managed intelligently behind the scene and perform very well for just about all purposes.

We can use Go's built in benchmarking tooling to see which implementation is faster. This is done in [slice_vs_linked_list_bench_test.go](./slice_vs_linked_list_bench_test.go). It can be executed by running `go test -bench=. -test.benchmem` in this directory. The output shows that the slice implementation is almost seven times faster.

```
pkg: github.com/spring1843/go-dsa/queue
BenchmarkLinkedListQueue-8 17956176 83.73 ns/op 56 B/op 1 allocs/op
BenchmarkSliceQueue-8 100000000 11.79 ns/op 45 B/op 0 allocs/op
PASS
ok github.com/spring1843/go-dsa/queue 3.775s
```

## Application

Expand Down
63 changes: 63 additions & 0 deletions queue/slice_vs_linked_list_bench_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package queue

import (
"container/list"
"errors"
"testing"
)

type (
linkedListQueue struct {
items *list.List
}

sliceQueue []int
)

func BenchmarkLinkedListQueue(b *testing.B) {
q := newLinkedListQueue()
for n := 0; n < b.N; n++ {
q.enqueue(n)
}
for n := 0; n < b.N; n++ {
q.dequeue()
}
}

func BenchmarkSliceQueue(b *testing.B) {
q := sliceQueue{}
for n := 0; n < b.N; n++ {
q.enqueue(n)
}
for n := 0; n < b.N; n++ {
q.dequeue()
}
}

func (q *sliceQueue) enqueue(val int) {
*q = append(*q, val)
}

func (q *sliceQueue) dequeue() (int, error) {
if len(*q) == 0 {
return 0, errors.New("queue is empty")
}
value := (*q)[0]
*q = (*q)[1:]
return value, nil
}

func newLinkedListQueue() *linkedListQueue {
return &linkedListQueue{items: list.New()}
}

func (q *linkedListQueue) enqueue(val int) {
q.items.PushBack(val)
}

func (q *linkedListQueue) dequeue() (int, error) {
if q.items.Len() == 0 {
return 0, errors.New("queue is empty")
}
return q.items.Remove(q.items.Front()).(int), nil
}

0 comments on commit 45da642

Please sign in to comment.