В этом руководстве мы рассмотрим основы четырех фундаментальных структур данных в JavaScript: массивов, связанных списков, стеков и очередей. Эти структуры данных необходимо знать любому начинающему разработчику программного обеспечения, и они используются в различных приложениях. Мы предоставим отдельный, более полный учебник для каждой отдельной упомянутой структуры данных. Не забудьте проверить это, когда вы закончите читать это.
Массивы
Массивы — это обычная структура данных, используемая в языках программирования для хранения коллекций данных. В JavaScript массивы являются динамическими и могут содержать элементы данных разных типов. Массивы индексируются, начиная с 0, и к ним можно получить доступ за постоянное время O(1).
Некоторые распространенные операции с массивами и их временная сложность:
- Доступ к элементу по индексу: O(1)
- Вставка элемента в конец массива: O(1)
- Вставка элемента в начало или середину массива: O(n)
- Удаление элемента с конца массива: O(1)
- Удаление элемента из начала или середины массива: O(n)
Вот пример создания и доступа к массиву в JavaScript:
let myArray = [1, 2, 3]; console.log(myArray[0]); // Output: 1
Связанные списки
Связный список — это структура данных, состоящая из узлов, содержащих значение и указатель на следующий узел в списке. Связанные списки используются, когда нам нужно часто вставлять или удалять элементы.
Некоторые распространенные операции со связанными списками и их временная сложность:
- Доступ к элементу по индексу: O(n)
- Вставка элемента в начало: O(1)
- Вставка элемента в конец: O(n)
- Удаление элемента с самого начала: O(1)
- Удаление элемента с конца: O(n)
Вот пример создания и доступа к связанному списку в JavaScript:
class ListNode { constructor(value) { this.value = value; this.next = null; } } class LinkedList { constructor() { this.head = null; this.tail = null; } addToTail(value) { const newNode = new ListNode(value); if (!this.head) { this.head = newNode; } else { this.tail.next = newNode; } this.tail = newNode; } removeHead() { if (!this.head) { return null; } const currentHead = this.head; if (this.head === this.tail) { this.tail = null; } this.head = this.head.next; return currentHead.value; } } let linkedList = new LinkedList(); linkedList.addToTail(1); linkedList.addToTail(2); linkedList.addToTail(3); console.log(linkedList.head.value); // Output: 1
Стеки
Стек — это структура данных, в которой элементы хранятся в порядке «последний пришел — первый ушел» (LIFO). Стеки используются для отслеживания вызовов функций, функций отмены/возврата и оценки выражений.
Некоторые распространенные операции со стеком и их временная сложность:
- Помещение элемента в стек: O(1)
- Извлечение элемента из стека: O(1)
- Взгляд на верхний элемент: O(1)
Вот пример создания и доступа к стеку в JavaScript:
class Stack { constructor() { this.items = []; } push(element) { this.items.push(element); } pop() { return this.items.pop(); } peek() { return this.items[this.items.length - 1]; } isEmpty() { return this.items.length === 0; } size() { return this.items.length; } } let stack = new Stack(); stack.push(1); stack.push(2); stack.push(3); console.log(stack.peek()); // Output: 3
Очереди
Очередь — это структура данных, в которой элементы хранятся в порядке «первым поступил — первым обслужен» (FIFO). Очереди используются в сценариях, где необходимо сохранить порядок добавления элементов, например при планировании заданий и распределении ресурсов.
Некоторые распространенные операции с очередью и их временная сложность:
- Добавление элемента в конец очереди (enqueue): O(1)
- Удаление элемента из начала очереди (dequeue): O(1)
- Просмотр первого элемента в очереди: O(1)
Вот пример создания и доступа к очереди в JavaScript:
class Queue { constructor() { this.items = []; } enqueue(element) { this.items.push(element); } dequeue() { return this.items.shift(); } peek() { return this.items[0]; } isEmpty() { return this.items.length === 0; } size() { return this.items.length; } } let queue = new Queue(); queue.enqueue(1); queue.enqueue(2); queue.enqueue(3); console.log(queue.peek()); // Output: 1
Понимание временной сложности имеет решающее значение при выборе правильной структуры данных для работы. Важно выбрать структуру данных, которая обеспечивает желаемые операции с наиболее эффективной временной сложностью. Используя правильную структуру данных, мы можем писать программы, которые оптимально работают даже с большими наборами данных.