Реализация связанного списка с примерами и анимацией
7 ноября 2022 г.связный список — одна из самых основных структур данных в информатике. В этой статье мы рассмотрим следующие темы:
- Преимущества и недостатки связанного списка по сравнению с массивами.
- Что такое связанный список?
- Вставка в связанный список (вставка узла).
- Удаление из связанного списка (удаление узла).
Что такое связанный список?
Это список узлов, где каждый узел содержит данные и указатель на следующий узел в списке. Это линейная структура данных, что означает, что ее можно пройти, следуя только одному указателю за раз. Первый узел называется головным, а последний — хвостовым. Хвостовой узел указывает на null.
class Node:
def __init__(self, data: int, next_node: 'Node' = None):
self.data = data
self.next = next_node
Вставка в связанный список (вставка узла)
Существует три способа вставки узла в связанный список:
- Вставить в начало списка.
- Вставить в конец списка.
- Вставить в указанную позицию.
Вставить в начало списка
Начнем с самого простого. Мы вставим узел в начало списка. Алгоритм состоит из следующих шагов:
- Создайте новый узел.
- Установите следующий указатель нового узла так, чтобы он указывал на голову.
- Установите голову так, чтобы она указывала на новый узел.
- Верните новую головку.
def insert_at_beginning(head: Node, data: int) -> Node:
new_node = Node(data)
new_node.next = head
return new_node
Давайте создадим список из 4 узлов с помощью этого метода:
head = None
for i in range(4):
head = insert_at_beginning(head, i + 1)
Временная сложность этого алгоритма составляет O(1), потому что мы меняем только указатель головы
Вставить в конец списка
Этот алгоритм немного сложнее, но все равно прост. Мы вставим узел в конец списка.
- Создайте новый узел.
- Установите следующий указатель нового узла равным нулю.
- Проходим по списку, пока не найдем последний узел.
- Установите следующий указатель хвостового узла так, чтобы он указывал на новый узел.
- Вернуть голову.
def insert_at_end(head: Node, data: int) -> Node:
new_node = Node(data)
if head is None:
return new_node
current = head
while current.next is not None:
current = current.next
current.next = new_node
return head
head = None
for i in range(5):
head = insert_at_end(head, i + 1)
Временная сложность этого алгоритма равна O(n), потому что мы перебираем список, пока не найдем хвост.
Вставить в указанную позицию.
Мы вставим узел в заданную позицию. Алгоритм состоит из следующих шагов:
- Создайте новый узел.
- Проходим по списку, пока не найдем узел в заданной позиции.
- Установите следующий указатель нового узла так, чтобы он указывал на узел в заданной позиции.
- Установите следующий указатель предыдущего узла так, чтобы он указывал на новый узел.
- Вернуть голову.
def insert_at_position(head: Node, data: int, position: int) -> Node:
new_node = Node(data)
if position == 0:
new_node.next = head
return new_node
current = head
current_position = 0
while current is not None and current_position < position - 1:
current = current.next
current_position += 1
if current is None:
return head
new_node.next = current.next
current.next = new_node
return head
Временная сложность этого алгоритма равна O(n), потому что мы перебираем список, пока не найдем узел в требуемой позиции
Вставить узел в позицию 0:
Вставить узел в позицию, превышающую длину списка:
Вставить узел в позицию между 0 и длиной списка:
Удаление из связанного списка
Есть три способа удалить узел из связанного списка:
- Удалить первый узел.
- Удалить последний узел.
- Удалить узел в указанной позиции.
Удалить первый узел
Алгоритм состоит из следующих шагов:
- Настройте голову так, чтобы она указывала на второй узел.
- Верните новую головку.
def delete_first(head: Node) -> Node:
if head is None:
return None
return head.next
Временная сложность этого алгоритма составляет O(1), потому что мы меняем только указатель головы.
Удалить последний узел
Алгоритм состоит из следующих шагов:
- Проходим по списку, пока не найдем предпоследний узел.
- Установите следующий указатель предпоследнего узла равным нулю.
- Вернуть голову.
def delete_last(head: Node) -> Node:
if head is None:
return None
if head.next is None:
return None
current = head
while current.next.next is not None:
current = current.next
current.next = None
return head
Временная сложность этого алгоритма равна O(n), потому что мы перебираем список, пока не найдем предпоследний узел.
Удалить узел в заданной позиции
Алгоритм состоит из следующих шагов:
- Проходим по списку, пока не найдем узел в заданной позиции.
- Установите следующий указатель предыдущего узла так, чтобы он указывал на узел после узла в заданной позиции.
- Вернуть голову.
def delete_at_position(head: Node, position: int) -> Node:
if position == 0:
return head.next
current = head
current_position = 0
while current is not None and current_position < position - 1:
current = current.next
current_position += 1
if current is None or current.next is None:
return head
current.next = current.next.next
return head
Временная сложность этого алгоритма равна O(n), потому что мы перебираем список, пока не найдем узел в требуемой позиции.
Заключение
В этой статье мы увидели, как реализовать связанный список в Python. Эта структура данных очень эффективна, когда вам нужно добавить или удалить элементы из начала списка. Его также очень легко реализовать.
Оригинал