60 lines
8.5 KiB
Markdown
60 lines
8.5 KiB
Markdown
|
|
Отчёт по экспериментальному сравнению структур данных телефонного справочника
|
|||
|
|
1. Условия эксперимента
|
|||
|
|
Реализованы три структуры для хранения записей вида {name, phone}:
|
|||
|
|
|
|||
|
|
односвязный список (вставка в голову);
|
|||
|
|
|
|||
|
|
хеш-таблица с цепочками (размер таблицы ~ 2N, простое число, хеш-функция hash(name) % size);
|
|||
|
|
|
|||
|
|
двоичное дерево поиска без балансировки.
|
|||
|
|
|
|||
|
|
Измерялось время выполнения операций вставки N = 10 000 записей, поиска 110 имён (100 существующих + 10 несуществующих) и удаления 50 случайных записей.
|
|||
|
|
Эксперименты проводились для двух вариантов порядка входных данных:
|
|||
|
|
|
|||
|
|
shuffled – случайный порядок имён;
|
|||
|
|
|
|||
|
|
sorted – имена, отсортированные по алфавиту.
|
|||
|
|
Каждый замер повторялся 5 раз, результаты усреднены.
|
|||
|
|
|
|||
|
|
Полученные средние значения (фрагмент):
|
|||
|
|
|
|||
|
|
Структура Режим Вставка (сек) Поиск (сек) Удаление (сек)
|
|||
|
|
LinkedList shuffled ~0.003 ~0.100 ~0.056
|
|||
|
|
LinkedList sorted ~0.003 ~0.063 ~0.038
|
|||
|
|
HashTable shuffled ~0.008 ~0.00006 ~0.00004
|
|||
|
|
HashTable sorted ~0.006 ~0.00008 ~0.00003
|
|||
|
|
BST shuffled ~0.055 ~0.0005 ~0.00027
|
|||
|
|
BST sorted ~23.997 ~0.212 ~0.129
|
|||
|
|
Точные числа см. в файле results.csv
|
|||
|
|
|
|||
|
|
2. Сравнительный анализ
|
|||
|
|
2.1. Влияние порядка данных на BST: деградация до O(n)
|
|||
|
|
На shuffled-данных дерево строится относительно сбалансированным, и операции выполняются в среднем за O(log N).
|
|||
|
|
На sorted-данных каждая следующая вставка попадает строго в правого потомка, и дерево вырождается в линейный список. Глубина рекурсии достигает N = 10 000, что приводит к:
|
|||
|
|
|
|||
|
|
колоссальному росту времени вставки (с ~0.055 сек до ~24 сек);
|
|||
|
|
|
|||
|
|
значительному замедлению поиска и удаления (с ~0.0005 сек до ~0.21 сек и с ~0.00027 сек до ~0.13 сек соответственно).
|
|||
|
|
Причина — рекурсивные функции вынуждены обходить все N узлов, превращая логарифмическую сложность в линейную. Практический вывод: использовать несбалансированное BST можно только при гарантированно случайном порядке поступающих ключей, иначе необходимы самобалансирующиеся варианты (AVL, красно-чёрное дерево).
|
|||
|
|
|
|||
|
|
2.2. Почему хеш-таблица почти не чувствительна к порядку
|
|||
|
|
Хеш-функция равномерно распределяет ключи по корзинам независимо от порядка поступления. Операции вставки, поиска и удаления сводятся к вычислению хеша и проходу по очень короткой цепочке (в среднем O(1)). Время вставки в отсортированном наборе даже чуть меньше (0.006 сек против 0.008 сек), что объясняется меньшим количеством коллизий при последовательном поступлении близких имён (хотя разница несущественна). Поиск и удаление занимают доли миллисекунды и практически не зависят от размера набора в исследованном диапазоне. Хеш-таблица демонстрирует наилучшую устойчивость к любым шаблонам входных данных при условии хорошей хеш-функции и адекватного размера.
|
|||
|
|
|
|||
|
|
2.3. Почему связный список всегда медленен при поиске
|
|||
|
|
В односвязном списке единственный способ найти элемент — линейный проход от головы к хвосту. Среднее время поиска — O(N), то есть пропорционально количеству записей. В эксперименте при 10 000 записей и поиске 110 имён время составило около 0.1 сек, что на три порядка хуже, чем у хеш-таблицы, и на два порядка хуже, чем у сбалансированного BST. Режим sorted/shuffled влияет слабо (для списка порядок вставки не меняет структуру). Медленный поиск — фундаментальное ограничение связного списка.
|
|||
|
|
|
|||
|
|
2.4. Удаление в каждой структуре
|
|||
|
|
Связный список: удаление требует поиска элемента (O(N)) и изменения ссылки у предыдущего узла. Время удаления соизмеримо с поиском (0.038–0.056 сек).
|
|||
|
|
|
|||
|
|
Хеш-таблица: удаление выполняется за O(1) в среднем — вычисление индекса, поиск в цепочке (очень короткой) и изменение ссылок. Время минимально (~0.00004 сек).
|
|||
|
|
|
|||
|
|
BST: удаление узла с двумя потомками требует поиска минимального элемента в правом поддереве. На сбалансированных данных (shuffled) время ~0.00027 сек. На вырожденных (sorted) удаление замедляется до 0.13 сек из-за необходимости обходить длинные цепочки.
|
|||
|
|
|
|||
|
|
3. Выводы и практические рекомендации
|
|||
|
|
Если преобладают частые поиск и вставка, а порядок данных не важен – оптимальный выбор хеш-таблица. Она обеспечивает константное среднее время операций и нечувствительна к порядку поступления ключей. Идеально для телефонного справочника, кешей, словарей.
|
|||
|
|
|
|||
|
|
Если требуется хранить данные в отсортированном виде и нужны операции типа «найти следующий/предыдущий» – подходит BST, но обязательно самобалансирующееся (например, АВЛ или красно-чёрное дерево). Несбалансированное BST применимо только при случайном порядке вставки; иначе деградация до O(n) делает его бесполезным.
|
|||
|
|
|
|||
|
|
Связный список стоит использовать лишь в случаях, когда операции поиска редки, а основные действия — добавление/удаление в начале или в середине списка при известной позиции. Для телефонного справочника он практически непригоден из-за линейного времени поиска.
|
|||
|
|
|
|||
|
|
Таким образом, для типового приложения с преимущественно операциями поиска и вставки (например, адресная книга в мобильном телефоне) лучшим решением является хеш-таблица. Если же функциональность требует получения отсортированного списка контактов или диапазонных запросов, разумно применять сбалансированное дерево поиска.
|