Лекции / Лекция_9_Структуры_данных_продолжение_ipynb_Colab (1)
.pdf
Оценка сложности операций
Операция |
Сложность операции в худшем случае |
Вставка элемента
Получение без удаления
Получение с удалением
Получение размера
Реализация на Python
Отсутствие массивов в Python Так как в Python отсутствует поддержка массивов, то реализация стека на их основе становится бессмысленной.
Очередь на основе двусвязного списка
Очередь — это абстрактный тип данных, представляющий собой список элементов, организованных по принципу FIFO (англ. first in — first out, «первым пришёл — первым вышел»).
Очередь — динамическая структура данных.
Поддерживаемые операции:
Добавление элемента в конец очереди (enqueue) Удаление элемента из головы очереди (dequeue) Получение головного элемента без удаления (peek)
Получение размера очереди
Реализация очереди на основе двусвязного списка
Пожалуй одной из самых простых реализаций очереди является использование двусвязного списка. У него операции добавления элемента в начало списка и удаления элемента с конца списка обладают константной сложностью, что делает его использование довольно оптимальным. К недостаткам стоит отнести повышенный расход памяти на хранение ссылок на элементы списка.
Добавление значения в конец очереди
Получение значения с удалением с головы очереди
Получение значения без удаления с головы очереди
Получение размера очереди
Для получения размера очереди стоит объявить переменную с начальным значением 0. Начиная с начала очереди выполнять переход по ссылке к следующему узлу. На каждом переходе увеличивать значение этой переменной на 1. Закончить на tail.
Реализация на Python
Описание структуры узла и очереди
class Node:
def __init__(self, data=None, next=None, prev=None):
#Инициализузладанныеция: ссылка,наследующий |
узелссылка, напредыдущийузел |
||
self.data=data |
|
|
|
self.next=next |
|
|
|
self.prev=prev |
|
|
|
def __str__(self): |
|
|
|
#Припреобразованиистрокувозвращаемданные |
узла(опечаткаdate->data): |
||
return str(self.data) |
|
||
class Queue: |
|
|
|
def __init__(self): |
|
||
#Создаёмфиктивныеузлыheadиtail |
|
||
self.head=Node |
() |
#Головачереди(фиктивныйузел) |
|
self.tail=Node |
() |
#Хвосточереди(фиктивныйузел) |
|
#Связываемheadиtail:headуказываетнаtail, |
tailуказываетнаhead |
||
self.head=.next |
self.tail |
|
|
self.tail=.prev |
self.head |
|
|
#Длинаочереди(количествореальныхузлов) |
|
||
self.length= |
|
0 |
|
Методы добавления в конец очереди |
|||
def enqueue(self, value): |
|
||
#Создаёмновыйузел: |
|
|
|
#-data=value |
|
|
|
#-next=self.head(текущий.nextпервыйреальный |
узел) |
||
#-prev=self.(headфиктивнаяголова) |
|
||
add_node=Node(value, |
|
self.head.next, self.head) |
|
#Текущийпервыйреальныйузелтеперьдолжен |
указыватьнановыйузелкакнапредыдущий |
||
self.head.next=add.prevnode |
|
||
#Головатеперьуказываетнановыйузелкакна |
первыйреальный |
||
self.head=.addnextnode |
|
|
|
#Увеличиваемдлинуочереди |
|
|
|
self.length+= |
1 |
|
|
Метод получения с удалением
def dequeue(self):
#Еслиочередьпустаничего, невозвращаем(или if self.is_empty():
return None
#Узелкоторый, нужноудалить(последнийреальный remove=_node self.tail.prev
#Хвосттеперьуказываетнапредыдущийперед self.tail=.removeprev_node.prev
#Новыйпоследнийреальныйузелтеперьуказывает remove_node=.prev.next self.tail
#Сохраняемданныеизудаляемогоузла return=removevalue_node.data
#Отвязывудаляемыйузел(длябезопасности) remove_node= .next None remove_node= .prev None
#Уменьшаемдлинуочереди self.length-= 1
#Возвращаемданныеудалённогоэлемента return return_value
Методы получения без удаления
def peek(self):
#Еслиочередьпустаничего, невозвращаем(или if self.is_empty():
return None
#Получаемпоследнийреальныйузел(перед remove=_node self.tail.prev
#Возвращаемданныеизузлабезегоудаления return remove_node.data
можновернутьNone)
узелперед, фиктивнымtail)
удаляемымузел
нахвосткакнаследующий
можновернутьNone)
фиктивнымtail)
Методы получения длины
def get_length(self): |
|
|
||
#Начинаспервогомреальногоузла(после |
фиктивногоhead) |
|||
current=_node |
self.head.next |
|
||
#Счётчикдлиныочереди |
|
|
||
length= |
0 |
|
|
|
#Проходимповсемреальнымузлампока,недойдём |
дофиктивногоtail |
|||
while current!=node |
self.tail: |
|
||
length+= |
|
1 |
|
#Увеличиваемсчётчик |
current=currentnode _node.next |
#Переходимкследующемуузлу |
|||
#Возвращаемколичествореальныхузловочереди return length
Очередь на основе массива
Реализация очереди на основе массива
Для реализации очереди можно использовать одномерные массивы. Такой подход позволит значительно снизить затраты памяти на хранение по сравнению с очередью на основе двусвязного списка (не нужно хранить множество ссылок на соседние элементы). Идея и реализация также довольно простые. С помощью двух переменных хранят индексы, указывающие на начало и конец очереди. Важной особенностью подобных индексов является их цикличность. Это означает, что дойдя до конца последовательности, они переходят в её начало.
Добавление значения в конец очереди (tail + 1 ≠ head)
Добавление значения в конец очереди (tail + 1 = head)
Получение значения с удалением с головы очереди
Получение значения без удаления с головы очереди
Уменьшение размера очереди
В большинстве случаев очередь на основе массива только увеличивает свой размер. Автоматического уменьшения не предусматривают. Для уменьшения размера используют функцию, вызов которой осуществляется по желанию разработчика.
Получение размера очереди
Для получения размера очереди стоит объявить переменную с начальным значением 0. Начиная с начала очереди добавляем к значению head и этой переменной единицу, до тех пор пока head не станет равно tail. Вернуть значение переменной.
Реализация на Python
Так как в Python отсутствует достаточная поддержка массивов, то реализация очереди на их основе не рассматривается.
Напишите программный код или сгенерируйте его с помощью искусственного интеллекта.
Чтобы изменить содержимое ячейки, дважды нажмите на нее (или выберите "Ввод")
Чтобы изменить содержимое ячейки, дважды нажмите на нее (или выберите "Ввод")
Чтобы изменить содержимое ячейки, дважды нажмите на нее (или выберите "Ввод")
Чтобы изменить содержимое ячейки, дважды нажмите на нее (или выберите "Ввод")
Чтобы изменить содержимое ячейки, дважды нажмите на нее (или выберите "Ввод")
Чтобы изменить содержимое ячейки, дважды нажмите на нее (или выберите "Ввод")
Чтобы изменить содержимое ячейки, дважды нажмите на нее (или выберите "Ввод")
Чтобы изменить содержимое ячейки, дважды нажмите на нее (или выберите "Ввод")
