Подтвердить что ты не робот

Есть ли реализация очереди?

Может ли кто-нибудь предложить контейнер Go для простой и быстрой FIF/очереди, Go имеет 3 разных контейнера: heap, list и vector. Какой из них более подходит для реализации очереди?

4b9b3361

Ответ 1

Любой вектор или список должен работать, но вектор - это, вероятно, путь. Я говорю это, потому что вектор, вероятно, будет выделяться реже, чем сбор списков и мусора (в текущей реализации Go) довольно дорого. В небольшой программе это, вероятно, не имеет значения.

Ответ 2

Фактически, если вы хотите, это простая и простая в использовании очередь fifo, срез предоставляет все, что вам нужно.

queue := make([]int, 0)
// Push
queue := append(queue, 1)
// Top (just get next element, don't remove it)
x = queue[0]
// Discard top element
queue = queue[1:]
// Is empty ?
if len(queue) == 0 {
    fmt.Println("Queue is empty !")
}

Конечно, мы полагаем, что мы можем доверять внутренней реализации append и slicing, чтобы избежать бесполезного изменения размера и перераспределения. Для базового использования это вполне достаточно.

Ответ 3

Удивлен, увидев, что никто не предлагал буферизованные каналы в любом случае для очереди FIFO с ограничениями размера.

//Or however many you might need + buffer.
c := make(chan int, 300)

//Push
c <- value

//Pop
x <- c

Ответ 4

Чтобы расширить область реализации, Moraes предлагает в его gist некоторая структура из очереди и стека:

// Stack is a basic LIFO stack that resizes as needed.
type Stack struct {
    nodes   []*Node
    count   int
}
// Queue is a basic FIFO queue based on a circular list that resizes as needed.
type Queue struct {
    nodes   []*Node
    head    int
    tail    int
    count   int
}

Вы можете увидеть это в действии в этом примере игровой площадки.

Ответ 5

Использование среза и соответствующей ( "круговой" ) схемы индексирования сверху все еще, кажется, путь. Здесь я беру на себя это: https://github.com/phf/go-queue В тестах также подтверждается, что каналы быстрее, но по цене более ограниченной функциональности.

Ответ 6

Slice может использоваться для реализации очереди.

type queue struct {
    values []*int
}

func New() *queue {
   queue := &queue{}
   return queue
}

func (q *queue) enqueue(val *int) {
   q.values = append(q.values, val)
}

//deque function

Update:

здесь полная реализация на моей странице GitHub https://github.com/raiskumar/algo-ds/blob/master/tree/queue.go

Ответ 7

Я также реализую очередь из среза, как указано выше. Тем не менее, он не является потокобезопасным. Поэтому я решил добавить блокировку (блокировку мьютекса), чтобы гарантировать потокобезопасность.

package queue

import (
  "sync"
)

type Queue struct {
  lock *sync.Mutex
  Values []int
}

func Init() Queue {
  return Queue{&sync.Mutex{}, make([]int, 0)}
}

func (q *Queue) Enqueue(x int) {
  for {
    q.lock.Lock()
    q.Values = append(q.Values, x)
    q.lock.Unlock()
    return
  }
}

func (q *Queue) Dequeue() *int {
  for {
    if (len(q.Values) > 0) {
      q.lock.Lock()
      x := q.Values[0]
      q.Values = q.Values[1:]
      q.lock.Unlock()
      return &x
    }
    return nil
  }
  return nil
}

Вы можете проверить мое решение на github здесь простая очередь