Skip to main content

Очередь

Описание

Очередь (queue) - это динамическая структура данных, в которой элементы хранятся в порядке их добавления. Она является примером линейной структуры или последовательной коллекции. Новые элементы добавляются в конец очереди (enqueue). Удаление элементов выполняется с начала очереди (dequeue). Таким образом, очередь реализует принцип "первым вошел - первым вышел" (first in - first out, FIFO). Кроме enqueue и dequeue, часто также реализуется операция чтения значения головного узла без его удаления (peek).

Иллюстрацией рассматриваемой структуры данных может служить любая очередь в обычной жизни, например, из тех, кто только спросить :D


Реализация

Для реализации очереди мы воспользуемся связным списком (см. раздел 1).

Говорить тут особо не о чем, так что привожу сразу весь код:

// data-structures/queue.js
// Импортируем конструктор связного списка
import LinkedList from './linked-list'

// Очередь
export default class Queue {
constructor() {
// Создаем связный список
this.list = new LinkedList()
}

// Проверяет, является ли очередь пустой
isEmpty() {
return !this.list.head
}

// Возвращает значение первого узла без его удаления
peek() {
if (this.isEmpty()) {
return null
}

return this.list.head.value
}

// Добавляет элемент в конец очереди
enqueue(value) {
this.list.append(value)
}

// Удаляет первый узел и возвращает его значение
dequeue() {
const removedHead = this.list.removeHead()
return removedHead?.value || null
}

// Преобразует очередь в строку.
// Принимает кастомную функцию стрингификации
toString(cb) {
return this.list.toString(cb)
}

// Преобразует очередь в массив значений
toArray() {
return this.list.toArray().map((node) => node.value)
}
}

Тестирование

Проверяем, что наша очередь работает, как ожидается:

// data-structures/__tests__/queue.test.js
import Queue from '../queue'

describe('Queue', () => {
it('должен создать пустую очередь', () => {
const queue = new Queue()
expect(queue).not.toBeNull()
expect(queue.linkedList).not.toBeNull()
})

it('должен добавить значения в очередь', () => {
const queue = new Queue()

queue.enqueue(1)
queue.enqueue(2)

expect(queue.toString()).toBe('1,2')
})

it('должен добавить/удалить объекты в/из очереди', () => {
const queue = new Queue()

queue.enqueue({ value: 'test1', key: 'key1' })
queue.enqueue({ value: 'test2', key: 'key2' })

const stringifier = (value) => `${value.key}:${value.value}`

expect(queue.toString(stringifier)).toBe('key1:test1,key2:test2')
expect(queue.dequeue().value).toBe('test1')
expect(queue.dequeue().value).toBe('test2')
})

it('должен извлечь значения из очереди без удаления и с удалением соответствующих узлов', () => {
const queue = new Queue()

expect(queue.peek()).toBeNull()

queue.enqueue(1)
queue.enqueue(2)

expect(queue.peek()).toBe(1)
expect(queue.peek()).toBe(1)
})

it('должен проверить пустоту очереди', () => {
const queue = new Queue()

expect(queue.isEmpty()).toBe(true)

queue.enqueue(1)

expect(queue.isEmpty()).toBe(false)
})

it('должен удалять элементы из очереди в порядке FIFO', () => {
const queue = new Queue()

queue.enqueue(1)
queue.enqueue(2)

expect(queue.dequeue()).toBe(1)
expect(queue.dequeue()).toBe(2)
expect(queue.dequeue()).toBeNull()
expect(queue.isEmpty()).toBe(true)
})
})

Запускаем тесты:

npm run test ./data-structures/__tests__/queue