Skip to content
Fast ring-buffer deque (double-ended queue)
Branch: master
Clone or download
Latest commit 46e4ffb May 21, 2019
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
.gitignore initial commit Apr 24, 2018
.travis.yml vet flag May 21, 2019
LICENSE Create LICENSE Apr 24, 2018
README.md Fix indent in README Sep 20, 2018
deque.go Merge pull request #5 from gammazero/new-func May 15, 2019
deque_test.go set minimum capacity at anytime May 15, 2019
doc.go Fix comment and golint warning. Move package comment into doc.go May 17, 2018
go.mod test with latest go May 21, 2019
go.test.sh update readme Apr 29, 2018

README.md

deque

Build Status Go Report Card codecov License

Extremely fast ring-buffer deque (double-ended queue) implementation.

GoDoc

For a pictorial description, see the Deque diagram

Installation

$ go get github.com/gammazero/deque

Deque data structure

Deque generalizes a queue and a stack, to efficiently add and remove items at either end with O(1) performance. Queue (FIFO) operations are supported using PushBack() and PopFront(). Stack (LIFO) operations are supported using PushBack() and PopBack().

Ring-buffer Performance

This deque implementation is optimized for CPU and GC performance. The circular buffer automatically re-sizes by powers of two, growing when additional capacity is needed and shrinking when only a quarter of the capacity is used, and uses bitwise arithmetic for all calculations. Since growth is by powers of two, adding elements will only cause O(log n) allocations.

The ring-buffer implementation significantly improves memory and time performance with fewer GC pauses, compared to implementations based on slices and linked lists. By wrapping around the buffer, previously used space is reused, making allocation unnecessary until all buffer capacity is used.

For maximum speed, this deque implementation leaves concurrency safety up to the application to provide, however the application chooses, if needed at all.

Reading Empty Deque

Since it is OK for the deque to contain a nil value, it is necessary to either panic or return a second boolean value to indicate the deque is empty, when reading or removing an element. This deque panics when reading from an empty deque. This is a run-time check to help catch programming errors, which may be missed if a second return value is ignored. Simply check Deque.Len() before reading from the deque.

Example

package main

import (
    "fmt"
    "github.com/gammazero/deque"
)

func main() {
    var q deque.Deque
    q.PushBack("foo")
    q.PushBack("bar")
    q.PushBack("baz")

    fmt.Println(q.Len())   // Prints: 3
    fmt.Println(q.Front()) // Prints: foo
    fmt.Println(q.Back())  // Prints: baz

    q.PopFront() // remove "foo"
    q.PopBack()  // remove "baz"

    q.PushFront("hello")
    q.PushBack("world")

    // Consume deque and print elements.
    for q.Len() != 0 {
        fmt.Println(q.PopFront())
    }
}

Uses

Deque can be used as both a:

  • Queue using PushBack and PopFront
  • Stack using PushBack and PopBack
You can’t perform that action at this time.