Добавил:
baraevaliza
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз:
Предмет:
Файл:Лабы по АиСД 2023 / Baraeva_Elizaveta_lb1
.pdf
МИНОБРНАУКИ РОССИИ
САНКТ-ПЕТЕРБУРГСКИЙ ГОСУДАРСТВЕННЫЙ
ЭЛЕКТРОТЕХНИЧЕСКИЙ УНИВЕРСИТЕТ
«ЛЭТИ» ИМ. В. И. УЛЬЯНОВА (ЛЕНИНА)
Кафедра МО ЭВМ
ОТЧЕТ
по лабораторной работе №1
по дисциплине «Алгоритмы и структуры данных»
Тема: Реализация и исследование развернутого связного списка
Студентка гр. 2383
Бараева Е. Н.
Преподаватель
Гаврилов А. В.
Санкт-Петербург
2023

2
Цель работы.
Реализация и тестирование развёрнутого связного списка, сравнение
производительности развёрнутого связного списка с массивом и связным
списоком.
Задание.
В рамках данной лабораторной работы необходимо реализовать “новую”
структуру, которая называется развернутым связным списком.
У данной структуры необходимо реализовать основные операции: поиск,
удаление, вставка, а также функцию вывода всего списка в консоль через
пробел. В качестве элементов для заполнения используются целые числа. Так
же при инициализации списка существует необязательный параметр n_array
(значение по умолчанию = 4), отвечающий за размер физического элемента
(т.е. за размер массива).
Для проверки работоспособности структуры необходимо реализовать
функцию (не метод класса) check, принимающую на вход два массива: массив
arr_1 для заполнения структуры, массив arr_2 для поиска и удаления, а также
необязательный параметр n_array (описан выше). Функция должна сначала
заполнять развернутый связный список данным arr_1, затем искать элементы
arr_2 и удалять их. После каждой операции по обновлению списка
необходимо осуществлять полный его вывод в консоль.
Помимо реализации описанного класса Вам необходимо провести
исследование его работы: сравнить время (дополнительные исследуемые
параметры, такие как память и на то, что Вам хватит фантазии - будут
плюсом) у реализованной структуры, массива (для Python используйте list,
для Cpp - стандартный массив ) и односвязного списка (код реализации
массива и односвязного списка загружать не нужно!).
Чтобы провести исследование необходимо проверить основные
операции на маленьком (около 10), среднем (10000) и большом (100000)
наборах данных для всех трёх случаев операции (лучший, средний, худший).

3
По итогам исследования в отчёте необходимо предоставить таблицу с
результатами замеров, а так же их графическое представление (на одном
графике необходимо изобразить одну операцию в одном случае для трёх
структур, т.е. суммарно должно получиться 9 графиков).
Выполнение работы.
В начале был создан класс Node, который хранил в себе массив и
указатель на следующий элемент. Затем был создан класс UnrolledLinkedList,
который принимал необязательный параметр n_array, который отвечал за
количество элементов в ноде, таже там была объявлена голова списка,
которой присвоилось None. Метод поиска искал элемент по значению и
возвращал индекс. С помощью цикла и переменной определялся массив, в
котором лежал элемент, и индекс. Если же список был пуст, то
выбрасывалось исключение, говорящее о пустоте списка, а если не
находилось элемента, то выводилось на экран сообщение о ненахождении
элемента. Метод вставки принимает элемент и индекс, на который его нежно
поставить. Были осуществлена проверка на корректность индекса. Если же
список был пуст и подавался индекс 0, то создавалась голова и туда клался
элемент, а сели список был пуст и индекс был не 0, то выбрасывалось
исключении о некорректности индекса. Затем с помощью цикла был найден
нод, куда нужно поместить элемент, если же он был заполнен, то
производилась балансировка, иначе элемент просто вставлялся в конец
массива. Вывод списка на экран осуществился также с помощью цикла.
Между элементами был пробел, а между надами стрелка, показывающая о
переходе на следующий нод. Метод удаления принимал индекс элемента, а
выводил его значение. В начале осуществлялась проверка на пустоту списка,
если он был пуст, то выбрасывалось исключение. Также если в списке лежал
только один элемент, то он удалялся и голове присваивалось None, говорящее
о пустоте списка. Если же индекс был меньше 0, то выбрасывалось
исключение. С помощью цикла находился массив, в котором лежал элемент и

4
удалялся, пустые ноды были также удалены. Также была реализована
функция проверки check, которая принимала два массива и необязательный
параметр n_array. Затем создавался список и с помощью двух циклов
проводилась вставка и удаление элементов, а между этими операциями
выводился весь список.
Разработанный программный код см. в приложении А.
Тестирование.
Результаты тестирования представлены в табл. 1.
Таблица 1 – Результаты тестирования
№
п/п
Входные данные
Выходные данные
Комментарии
1.
unrolled_list =
UnrolledLinkedList()
unrolled_list.insert(25, 0)
unrolled_list.insert(5, 0)
unrolled_list.insert(9, 2)
unrolled_list.insert(0, 0)
unrolled_list.insert(7, 4)
unrolled_list.print()
0 5 25 9 -> 7
Проверка
вставки.
Верно.
2.
unrolled_list =
UnrolledLinkedList()
for i in range(10):
unrolled_list.insert(i*i, i)
unrolled_list.remove(9)
unrolled_list.remove(0)
unrolled_list.remove(4)
unrolled_list.print()
1 4 9 -> 16 36 49 -> 64
Проверка
удаления
элемента.
Верно.
3.
unrolled_list =
UnrolledLinkedList(3)
for i in range(10):
unrolled_list.insert(i*i, i)
unrolled_list.print()
print(unrolled_list.search(4)
, unrolled_list.search(49))
0 1 4 -> 9 16 25 -> 36 49
64 -> 81
2 7
Проверка
поиска элемента
по индексу.
Верно.

5
Вывод.
Был реализован и протестирован развёрнутый связный список. Данный
список комбинирует плюсы массива и списка, т. е. вставка и удаление
быстрее обычный массив и списка, поиск медленнее, чем массив, но быстрее,
чем список. Результаты тестирования не соответствуют теоретическим, за
исключением поиска. Скорее всего это произошло из-за недостаточно
исправно работающего ноутбука или помех других параллельно работающих
программ, т.к. на другом компьютере все результаты тестирования сошлись с
теоретическими.

6
ПРИЛОЖЕНИЕ А
ИСХОДНЫЙ КОД ПРОГРАММЫ
Название файла: main.py
class Node:
def __init__(self):
self.array = []
self.next = None
class UnrolledLinkedList:
def __init__(self, n_array=4):
self.head = None
if n_array <= 0:
raise Exception("Wrong length of array")
self.n_array = n_array
def search(self, value):
if self.head is None:
raise Exception("The list is empty")
current = self.head
counter = 0
while current:
if value in current.array:
return counter + current.array.index(value)
else:
counter += len(current.array)
current = current.next
print("The item is not in the list")
def insert(self, value, index):
if index < 0:
raise Exception("Wrong index")
if self.head is None and index == 0:
self.head = Node()
self.head.array.append(value)
return
if self.head is None and index != 0:
raise Exception("Wrong index")
current = self.head
counter = 0
while current:
if counter <= index < counter + self.n_array:
if len(current.array) < self.n_array:
current.array.insert(index - counter, value)
return
else:
i = self.n_array // 2
temporary_arr = current.array[i:]
while i != len(current.array):
current.array.pop(i)
if current.next is None:
current.next = Node()
current.next.array = temporary_arr
else:
temporary_node = Node()

7
temporary_node.array = temporary_arr
temporary_node.next = current.next
current.next = temporary_node
if counter + len(current.array) > index:
current.array.insert(index - counter,
value)
else:
counter += len(current.array)
current.next.array.insert(index - counter,
value)
return
else:
counter += len(current.array)
if current.next is None:
previous = current
current = current.next
if counter == index:
new_node = Node()
new_node.array.append(value)
previous.next = new_node
return
raise Exception("Wrong index")
def print(self):
if self.head is None:
print("The list is empty")
return
current = self.head
while current:
for elem in current.array:
print(elem, end=" ")
if current.next is not None:
print("->", end=" ")
current = current.next
print()
def remove(self, index):
if self.head is None:
raise Exception("The list is empty")
if index == 0 and len(self.head.array) == 1:
self.head = self.head.next
return
if index < 0:
raise Exception("Wrong index")
current = self.head
counter = 0
while current:
if counter + len(current.array) > index:
current.array.pop(index - counter)
if len(current.array) == 0:
previous.next = previous.next.next
return
return
else:
counter += len(current.array)
previous = current
current = current.next
raise Exception("Wrong index")

8
def check(arr_1, arr_2, n_array=4):
unrolled_list = UnrolledLinkedList(n_array)
for i in range(len(arr_1)):
unrolled_list.insert(arr_1[i], i)
unrolled_list.print()
for elem in arr_2:
index = unrolled_list.search(elem)
unrolled_list.remove(index)
unrolled_list.print()
Название файла: test.py
import main
import random
import time
inpt = [random.randint(-50, 50) for i in range(50)]
delete = random.sample(inpt, 25)
main.check(inpt, delete)
def test(lim):
unrolled_list = main.UnrolledLinkedList()
array = list()
linked_list = LinkedList()
test_array = [random.randint(-50, 50) for _ in range(lim)]
print("Вставка в конец:")
start = time.time()
for i in range(lim):
array.append(test_array[i])
end = time.time()
print((end - start) * 10 ** 3, "ms")
start = time.time()
for i in range(lim):
unrolled_list.insert(test_array[i], i)
end = time.time()
print((end - start) * 10 ** 3, "ms")
start = time.time()
for i in range(lim):
linked_list.append(test_array[i])
end = time.time()
print((end - start) * 10 ** 3, "ms", '\n')
print("Поиск:")
start = time.time()
for i in range(lim):
array.index(test_array[i])
end = time.time()
print((end - start) * 10 ** 3, "ms")
start = time.time()
for i in range(lim):
unrolled_list.search(test_array[i])
end = time.time()

9
print((end - start) * 10 ** 3, "ms")
start = time.time()
for i in range(lim):
linked_list.search(test_array[i])
end = time.time()
print((end - start) * 10 ** 3, "ms", '\n')
print("Удаление с конца:")
start = time.time()
for i in range(lim):
array.pop()
end = time.time()
print((end - start) * 10 ** 3, "ms")
start = time.time()
for i in range(lim - 1, -1, -1):
unrolled_list.remove(i)
end = time.time()
print((end - start) * 10 ** 3, "ms")
start = time.time()
for i in range(lim):
linked_list.pop()
end = time.time()
print((end - start) * 10 ** 3, "ms", '\n')
test(1000)
test(10000)
test(50000)

10
ПРИЛОЖЕНИЕ Б
ГРАФИКИ
Рисунок 1 – вставка в конец малого количества данных
Рисунок 2 – поиск малого количества данных
Рисунок 3 – удаление с конца малого количества данных
Соседние файлы в папке Лабы по АиСД 2023
