← Назад к вопросам

По какому принципу работает очередь как структура данных

2.0 Middle🔥 192 комментариев
#Soft Skills и рабочие процессы

Комментарии (2)

🐱
deepseek-v3.2PrepBro AI4 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Принцип работы очереди как структуры данных

Очередь — это линейная структура данных, работающая по принципу FIFO (First In, First Out — «первым пришёл, первым ушёл»). Этот принцип аналогичен реальной очереди, например, в магазине: первый вставленный элемент будет первым извлечённым, а новые элементы добавляются в конец.

Ключевые операции и их принципы

Основные операции, обеспечивающие функционирование очереди:

  • Enqueue (постановка в очередь): Добавление нового элемента в конец (tail/rear) очереди.
  • Dequeue (удаление из очереди): Извлечение и удаление элемента из начала (head/front) очереди.
  • Peek/Front (просмотр): Получение значения элемента в начале очереди без его удаления.
  • isEmpty (проверка на пустоту): Проверка, содержит ли очередь элементы.
  • isFull (проверка на заполненность): Актуально для реализации на массиве фиксированного размера.

Внутреннее устройство и реализации

Принцип FIFO может быть реализован различными способами, что влияет на производительность операций.

1. Реализация на массиве (кольцевой буфер) Используется массив фиксированного размера и два указателя (индекса): front (начало) и rear (конец). При достижении конца массива указатели «закольцовываются» на начало, если там есть свободное место.

class Queue {
  constructor(capacity) {
    this.items = new Array(capacity);
    this.front = 0;
    this.rear = -1;
    this.size = 0;
    this.capacity = capacity;
  }

  enqueue(item) {
    if (this.isFull()) {
      throw new Error('Queue is full');
    }
    this.rear = (this.rear + 1) % this.capacity; // Кольцевое движение
    this.items[this.rear] = item;
    this.size++;
  }

  dequeue() {
    if (this.isEmpty()) {
      throw new Error('Queue is empty');
    }
    const item = this.items[this.front];
    this.front = (this.front + 1) % this.capacity; // Кольцевое движение
    this.size--;
    return item;
  }

  peek() {
    if (this.isEmpty()) {
      return null;
    }
    return this.items[this.front];
  }

  isEmpty() {
    return this.size === 0;
  }

  isFull() {
    return this.size === this.capacity;
  }
}

Принцип: Эффективность O(1) для основных операций, но требуется управление указателями и есть ограничение по размеру.

2. Реализация на связном списке Более гибкая реализация, использующая узлы (Node). Указатель head указывает на первый узел, tail — на последний.

class Node {
  constructor(value) {
    this.value = value;
    this.next = null;
  }
}

class LinkedListQueue {
  constructor() {
    this.head = null; // Начало очереди
    this.tail = null; // Конец очереди
    this.length = 0;
  }

  enqueue(value) {
    const newNode = new Node(value);
    if (this.isEmpty()) {
      this.head = newNode;
      this.tail = newNode;
    } else {
      this.tail.next = newNode; // Присоединяем новый узел в конец
      this.tail = newNode;      // Обновляем указатель на хвост
    }
    this.length++;
  }

  dequeue() {
    if (this.isEmpty()) {
      return null;
    }
    const removedNode = this.head;
    this.head = this.head.next; // Сдвигаем начало на следующий узел
    if (this.head === null) {   // Если очередь опустела
      this.tail = null;
    }
    this.length--;
    return removedNode.value;
  }

  peek() {
    return this.head ? this.head.value : null;
  }

  isEmpty() {
    return this.length === 0;
  }
}

Принцип: Динамическое изменение размера, каждая операция enqueue/dequeue работает за O(1), так как добавление/удаление происходит с разных концов списка.

Вариации очередей

Принцип FIFO модифицируется для решения специфических задач:

  • Двусторонняя очередь (Deque) — позволяет добавлять и удалять элементы как с начала, так и с конца, объединяя принципы стека и очереди.
  • Циклическая очередь (Circular Queue) — использует кольцевой буфер для эффективного переиспользования памяти.
  • Очередь с приоритетом (Priority Queue) — нарушает принцип строгого FIFO. Элементы добавляются согласно их приоритету (часто реализуется через кучу). Извлекается всегда элемент с наивысшим приоритетом.

Принцип работы в контексте Event Loop

В веб-разработке принцип очереди фундаментален для Event Loop в JavaScript. Асинхронные операции (колбэки из setTimeout, промисы, события) помещаются в очередь задач (Task Queue) или очередь микрозадач (Microtask Queue). Event Loop непрерывно проверяет стек вызовов (Call Stack) и, когда он пуст, извлекает (dequeue) первую задачу из очереди и помещает её в стек на выполнение, строго соблюдая FIFO в пределах своих типов очередей.

console.log('1'); // Синхронная операция

setTimeout(() => console.log('2'), 0); // Макрозадача -> Task Queue

Promise.resolve().then(() => console.log('3')); // Микрозадача -> Microtask Queue

console.log('4'); // Синхронная операция
// Вывод: 1, 4, 3, 2
// Принцип: Синхронный код выполняется первым, затем Event Loop DEQUEUE микрозадачи из Microtask Queue, и только затем — макрозадачи из Task Queue.

Таким образом, принцип работы очереди — это не только абстрактная концепция структур данных, но и краеугольный камень управления асинхронностью, планирования задач и организации данных в бесчисленных областях программирования.