Skip to content

Commit bd6a6f8

Browse files
agorinenkoAnton Gorinenko
andauthored
Односвязный и двусвязный списки
Co-authored-by: Anton Gorinenko <[email protected]>
1 parent aaefa05 commit bd6a6f8

File tree

5 files changed

+84
-4
lines changed

5 files changed

+84
-4
lines changed

img/doubly_linked_list.png

20.4 KB
Loading

img/doubly_linked_list_1.png

31.3 KB
Loading

img/doubly_linked_list_2.png

32.3 KB
Loading

tutorial/doubly_linked_list.md

Lines changed: 78 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,81 @@
11
## Двусвязный список
22

33
В то время как объекты односвязного списка хранят ссылки только на следующие элементы, в двусвязном списке присутствуют
4-
обе связи на следующий и предыдущий элементы.
4+
обе связи на следующий и предыдущий элемент.
5+
6+
![img.png](../img/doubly_linked_list.png)
7+
8+
На рисунке выше синяя стрелка отображает связь на следующий элемент, а зеленая - на предыдущий. ``HEAD`` -
9+
указатель, хранящий ссылку на головной узел. Заметим, что доступ к хвосту списка осуществляется за счет ``HEAD`` и связи
10+
на предыдущий элемент ``prev``.
11+
12+
Каждый узел в двусвязном списке содержит не только значение, но и ссылку на следующий и предыдущий элемент. Программно
13+
его можно представить так:
14+
15+
```
16+
class DoublyListNode:
17+
"""
18+
Узел двусвязного списка
19+
"""
20+
def __init__(self, value, next_node, prev_node):
21+
self.value = value
22+
self.prev_node = prev_node
23+
self.next_node = next_node
24+
```
25+
26+
Как и односвязный список, двусвязный также имеет два указателя ``HEAD`` и ``TAIL`` на корневой ``head`` и
27+
конечный ``tail`` узлы соответственно.
28+
29+
## Линейный поиск и доступ к элементу по индексу по двусвязному списку
30+
31+
Аналогично односвязному списку, в двусвязном мы также имеем:
32+
33+
1. Мы не можем получить доступ к произвольному элементу за константное время.
34+
2. Для поиска значения в списке необходимо обойти все элементы начиная с головного.
35+
3. В худшем случае поиск элемента занимает линейное время **O(n)**.
36+
37+
## Вставка элемента в двусвязный список
38+
39+
Рассмотрим три вида вставки: вставка элемента в середину, в "голову" и в "хвост".
40+
41+
![img.png](../img/doubly_linked_list_1.png)
42+
43+
Вставку элемента в середину можно разделить на два шага:
44+
45+
1. Связывания вставляемого элемента ``cur`` с узлами ``prev`` и ``next``
46+
2. Удаление старых связей ``prev``->``next`` и дальнейшее их переназначение на ``cur``
47+
48+
Операция займет **O(n)** вне зависимости от того какой узел следующий или предыдущий задается. В отличие от односвязного
49+
списка мы располагаем двумя связями.
50+
51+
Вставка в голову и хвост аналогична тому, как это осуществляется в односвязном списке. Всегда ее сложность оценивается в
52+
**O(1)**.
53+
54+
Временная сложность операций:
55+
56+
Вставка элемента в середину - **O(1)**.
57+
58+
Вставка элемента в "голову" - **O(1)**
59+
60+
Вставка элемента в "хвост" - **O(1)**.
61+
62+
## Операция удаления элемента
63+
64+
Рассмотрим удаление из середины.
65+
66+
![img.png](../img/doubly_linked_list_2.png)
67+
68+
В отличие от односвязного списка, где эта операция занимает **O(n)** из-за того, что нам требуется найти предыдущий
69+
элемент для создания связи, двусвязный список имеет ссылку на ``prev``. Если мы хотим удалить существующий узел ``cur``,
70+
мы можем просто связать его предыдущий узел ``prev`` со следующим узлом ``next``. Временная сложность **O(1)**.
71+
72+
Удаление из начала и конца списка является частным случаем удаление из середины, поэтому имеет временную сложность **O(
73+
1)**.
74+
75+
Временная сложность операций:
76+
77+
Удаление элемента из "головы" - **O(1)**
78+
79+
Удаление элемента из середины - **O(1)**
80+
81+
Удаление элемента из "хвоста" - **O(1)**

tutorial/singly_linked_list.md

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
11
# Связанные списки
22

33
Связанный список - это линейная структуры данных, элементы в которой хранят ссылки на следующие объекты списка и
4-
располагаются в разных фрагментах памяти. Различают односвязные и двусвязные списки. На рисунке выше изображены оба вида
5-
этой структуры данных. Синяя стрелка отображает связь на следующий элемент, а зеленая - на предыдущий.
4+
располагаются в разных фрагментах памяти. Различают односвязные и двусвязные списки.
65

76
## Односвязный список
87

98
![Односвязный список](../img/singly_linked_list.png)
109

10+
На рисунке выше синяя стрелка отображает связь на следующий элемент. ``HEAD`` и ``TAIL`` -
11+
указатели, хранящие ссылки на головной и конечный узлы.
12+
1113
Каждый узел в односвязном списке содержит не только значение, но и ссылку на следующий элемент. Программно его можно
1214
представить так:
1315

@@ -82,7 +84,8 @@ class SinglyListNode:
8284

8385
Вставка элемента в "голову" - **O(1)**
8486

85-
Вставка элемента в "хвост" - **O(1)**. При условии, что список хранит указатель ``TAIL`` на последний элемент.
87+
Вставка элемента в "хвост" - **O(1)**. При условии, что список хранит указатель ``TAIL`` на последний элемент, иначе *
88+
*O(1)**.
8689

8790
## Удаление элемента из односвязного списка
8891

0 commit comments

Comments
 (0)