Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Лабы по АиСД 2023 / Baraeva_Elizaveta_lb1

.pdf
Скачиваний:
0
Добавлен:
09.09.2026
Размер:
273 Кб
Скачать
МИНОБРНАУКИ РОССИИ
САНКТ-ПЕТЕРБУРГСКИЙ ГОСУДАРСТВЕННЫЙ
ЭЛЕКТРОТЕХНИЧЕСКИЙ УНИВЕРСИТЕТ
«ЛЭТИ» ИМ. В. И. УЛЬЯНОВА (ЛЕНИНА)
Кафедра МО ЭВМ
ОТЧЕТ
по дисциплине «Алгоритмы и структуры данных»
Тема: Реализация и исследование развернутого связного списка
Студентка гр. 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