Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
1. Алгоритми та обчислювальна складність.docx
Скачиваний:
78
Добавлен:
17.07.2024
Размер:
1.55 Mб
Скачать

1.1.3. Кортежі, множини, словники, одно- та двобічнозв'язні списки. Реалізація абстрактних типів даних з оцінюванням складності операцій

Кортеж або n-ка — в математиці впорядкована та скінченна сукупність елементів (нескінченний кортеж має назву сімейства).

Кількість елементів в кортежі визначає його довжину. Так, кортеж з двох елементів (тобто довжини 2) називається двійкою, з трьох елементів — трійкою і т. д. Кортеж з n елементів називається n-кою.

У реляційних базах даних, кортеж — це елемент відношення. Для N-арного відношення кортеж є упорядкованим набором з N значень, по одному значенню для кожного атрибута відношення.

Однозв'язний список — вид зв'язаного списку, який складається з вузлів, кожен з яких містить у собі дані (інформаційну частину) та посилання на наступний вузол.

Найчастіше вузлом списку вважають структурний тип (структуру), який зберігає у собі певну інформаційну частину (іншу структуру або тип даних) та посилання (вказівник) на наступний вузол у списку. Список має «голову» head, тобто вказівник на початок списку та інколи має кінець tail, проте найчастіше його не використовують.

Переваги списків над масивами:

  • Можливість додавати вузол у кінець списку. Масив має статичний розмір, і, якщо, вільного місця там немає, доведеться створювати масив більшого розміру, копіювати у нього елементи «старого» масиву і тільки після цього додавати новий елемент

  • Можливість видаляти вузол і звільнювати пам'ять, яку він займав. У масиві можна лише зсунути елементи і розглядати його, як масив меншого розміру. Пам'ять при цьому не звільняється.

  • Можливість вставляти вузол у середину списку. При умові, що масив не заповнений до кінця, можна «розсунути» елементи і вставити між ними необхідний. Якщо ж масив повний — доведеться створювати новий масив більшого розміру, копіювати елементи і вставляти новий.

Недоліки списків перед масивами:

  • Відсутність поіндексного доступу до елементів списку

  • Зайвий час на прохід по списку для пошуку/видалення/додавання елементу у кінець

  • Використання більшого об'єму пам'яті за рахунок покажчиків на наступний вузол

Операції зі списками

Двобічно зв'язаний список — вид зв'язаного списку, у якому посилання в кожному вузлі вказують на попередній і на подальший вузол у списку.

Якщо в списку після останнього елемента йде перший, то такий список називається кільцевим двобічно зв'язаним списком. Тобто, поле prev голови списку вказує на хвіст списку, а поле next хвоста списку вказує на голову списку.

По двобічно зв'язаному списку можна пересуватися в будь-якому напрямку — як від початку до кінця, так і навпаки. Для нього простіше проводити видалення і перестановку елементів, оскільки завжди відомі адреси тих елементів списку, вказівник яких спрямований на змінюваний елемент.

Переваги двобічно зв'язаного списку над однобічно зв'язаним списком

  • Додавання нового вузла в певну позицію.

  • Видалення i-го елемента з послідовності.

  • Перегляд списку в обох напрямках.

Існують і недоліки: з'являється додаткова змінна — вказівник на попередній елемент (prev). У даній статті описаний принцип роботи двобічно зв'язного циклічного списку. Єдина відмінність двобічно зв'язного циклічного списку від двобічно зв'язного списку в тому, що останній елемент указує на перший, а перший — на останній. Дана відмінність дає змогу виключати перевірки на «перший» і «останній» елемент. Двобічно зв'язаний циклічний список (далі просто Двобічно зв'язаний список) візуально можна представити в наступному вигляді (рис.1):

Реалізація АТД означає забезпечення однієї процедури або функції для кожної абстрактної операції. Екземпляри АДТ представлені будь-якою конкретною структурою даних, яка маніпулює цими процедурами, відповідно до специфікації АТД.

Як правило, існує багато способів реалізувати той же АТД, з використанням декількох різних конкретних структур даних. Так, наприклад, абстрактний стек може бути реалізований за допомогою зв'язаного списку або масивом.

Для того, щоб запобігти клієнтів від залежності від реалізації, АТД часто упакований в вигляді непрозорого типу даних в одному або декількох модулях, чий інтерфейс містить тільки підпис (кількість і типи параметрів і результатів) від операцій. Реалізація модуля, а саме тіла процедур і конкретна структура даних, яка використовується — тоді можуть бути приховані від більшості клієнтів модуля. Це дає можливість змінити реалізацію, не зачіпаючи клієнтів. Якщо реалізація піддається впливу, відомо, замість цього, як прозорий тип даних.

При реалізації АТД, кожен екземпляр (в термінах імперативного стилю) або кожне стан (в термінах функціонального стилю), як правило, представлений дескриптором якогось виду.

Сучасні об'єктно-орієнтовані мови, такі як C++ і Java, підтримують форму абстрактних типів даних. Коли клас використовується як тип, це абстрактний тип, який відноситься до прихованого уявлення. У цій моделі АТД зазвичай реалізується як клас, і кожен екземпляр АТД, як правило, об'єкт цього класу. Інтерфейс модуля зазвичай оголошує конструктори, як звичайні процедури, і більшість інших операцій АТД, як методи цього класу. Проте, такий підхід не легко інкапсулювати декілька репрезентативних варіанти, знайдених в АТД. Вона також може підірвати розширюваності об'єктно-орієнтованих програм. У чисто об'єктно-орієнтованої програми, яка використовує інтерфейси як типи, типи відносяться до поведінці, не уявленню.

Крім поведінки з точки зору аксіом, можна також включити, в визначенні операції АТД, їх алгоритмічної складності. Олександр Степанов, дизайнер стандартної бібліотеки шаблонів C++, включені гарантії складності в специфікації STL, аргументуючи:

Причина введення поняття абстрактних типів даних було дозволити взаємозамінність програмних модулів. Ви не можете мати змінні модулі, якщо ці модулі не поділяють подібну поведінку складності. Якщо замінити один модуль іншим модулем з тією же функціональною поведінкою, але з різними компромісами складності, користувач цього коду буде неприємно здивований. Я міг би сказати йому що-небудь, що мені подобається абстракції даних, і він до цих пір не хотів би використовувати код. Складність твердження мають бути частиною інтерфейсу.