Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
СТА (лекции+лабы) / СТА Лаба 3.docx
Скачиваний:
51
Добавлен:
16.03.2016
Размер:
66.08 Кб
Скачать

Варианты амбициозного уровня

Вариант №16:

Реализуйте структуру-множество целых чисел на основе 2-3 дерева. Для упрощения задачи разрешается опустить операцию удаления узлов. 2-3 дерево – дерево с двумя типами узлов:

  • листья, хранящие конкретные значения;

  • внутренние узлы, содержащие 3 связи с дочерними узлами и минимальные значения, хранящиеся во втором и третьем поддереве.

Внутренние узлы могут содержать как 2, так и 3 поддерева. Если остается только 1 поддерево, узел уничтожается и заменяется поддеревом. Если требуется 4 поддерева, узел разрывается пополам и вводится еще один уровень глубины.

Проведите измерения производительности операции вставки и максимальной высоты в создаваемом дереве на достаточно больших множествах для:

  • последовательности элементов в случайном порядке;

  • последовательности элементов, отсортированной по возрастанию;

  • последовательности элементов, отсортированной по убыванию.

Подробнее о данной структуре можно прочесть по следующей ссылке:

  • Р. Седжвик, глава 13 “Сбалансированные деревья”, раздел 13.3 “Нисходящие 2-3-4 деревья”

Вариант №17:

Реализуйте структуру и основные операции автоматически балансирующегося BST на основе алгоритма, предполагающего рандомизированное вращение узлов дерева при вставке. Проведите измерения производительности операции вставки и максимальной высоты в создаваемом дереве на достаточно больших множествах для:

  • последовательности элементов в случайном порядке;

  • последовательности элементов, отсортированной по возрастанию;

  • последовательности элементов, отсортированной по убыванию.

Подробнее о данной структуре можно прочитать по следующей ссылке:

  • Р. Седжвик, глава 13 “Сбалансированные деревья”, раздел 13.1 “Рандомизированные BST-деревья”.

Вариант №18:

Разреженная матрица представляет собой матрицу со специальным способом хранения, ориентированным на экономию памяти. Ключевая идея разреженной матрицы состоит в том, чтобы хранить значения только тех коэффициентов, которые отличны от 0. Хранение можно реализовать при помощи хэш-таблицы, у которой в качестве ключа выступает пара индексов матрицы (номер столбца и номер строки), а в качестве значения – хранимый коэффициент. В качестве хэш-функции подойдет функция, складывающая номер строки с номером столбца, умноженным на количество строк. Необходимо реализовать следующие операции и проверить их работу при помощи достаточно полной тестовой программы:

  • Функцию создания матрицы, принимающую число строк и чисто столбцов. Изначально матрица должна предполагать, что все хранимые коэффициенты равны 0.

  • Функцию уничтожения матрицы.

  • Функции доступа и модификации конкретной ячейки матрицы по индексам.

  • Функцию печати матрицы в поток – на стандартный поток вывода по умолчанию.

  • Функции сложения, вычитания и умножения матриц.

  • Функцию транспонирования матрицы.

Контрольные вопросы

  1. Понятие хэш-функции. Основные требования к хэш-функциям. Понятие коллизии.

  2. Разрешение коллизий в хэш-таблицах в случае открытого хэширования.

  3. Разрешение коллизий в хэш-таблицах в случае закрытого хэширования.

  4. АТД “Дерево”. Виды узлов в дереве. Высота дерева. Полное и неполное дерево. Арность дерева. Обход деревьев.

  5. АТД “Дерево”: описание реализации на основе массива индексов родительских узлов.

  6. АТД “Дерево”: описание реализации на основе списков дочерних узлов.

  7. АТД “Дерево”: описание реализации на основе динамической структуры узлов.

  8. Бинарное дерево поиска. Характеристическое свойство. Вычислительная сложность всех операций. Сбалансированное и несбалансированное дерево.

  9. Операция вращения узлов в BST. Свойства, принцип реализации.

  10. Основные принципы организации красно-черных BST-деревьев. Дополнительные свойства-ограничения. Примеры корректирующих действий.

Пример решения задачи базового уровня

Задача:Пользователь вводит в программу последовательность целых чисел, завершая ввод нажатием <Ctrl+Z>. Числа могут повторяться. Программа собирает вводимые данные в память, а в конце ввода в произвольном порядке выдает набор из пар чисел на отдельных строках - первое из которых является одним из введенных чисел без повторений, а второе - количество его появлений во вводе. Например, пользователь вводит такую последовательность :

1 2 3 4 5 1 3 5 6 1 <Ctrl+Z>

На что программа выдает следующий результат обработки (строки могут быть в любом порядке):

1 3

2 1

3 2

4 1

5 2

6 1

Реализация на основе хэш-таблиц:

Для реализации задачи требуется реализовать функцию обхода хранящихся ячеек в хэш-таблице. В заголовочный файл с хэш-таблицей (hash_table.hpp) следует добавить такое объявление для функции обхода, которая будет отправлять пару ключ-значение функции обратного вызова:

typedef void ( * HashTableWalkFunction ) ( int _key, int _value );

void HashTableWalk ( const HashTable & _ht, HashTableWalkFunction _f );

Можно реализовать такую функцию для таблицы с закрытым хэшированием. Для этого нужно в файл реализации hash_table_closed_impl.cpp добавить тело функции обхода:

void HashTableWalk ( const HashTable & _ht, HashTableWalkFunction _f )

{

// Находим ячейки, имеющие статус OCCUPIED, и вызываем функцию пользователя

for ( int i = 0; i < _ht.m_tableSize; i++ )

if ( _ht.m_pData[ i ].m_status == HashTable::Element::OCCUPIED )

( * _f )( _ht.m_pData[ i ].m_key, _ht.m_pData[ i ].m_value );

}

В качестве альтернативы, такую же функции можно добавить в таблицу с открытым хэшированием. Для этого файл реализации hash_table_open_impl.cpp следует расширить:

void HashTableWalk ( const HashTable & _ht, HashTableWalkFunction _f )

{

// Находим ячейки, имеющие списки

for ( int i = 0; i < _ht.m_tableSize; i++ )

if ( _ht.m_pData[ i ] )

{

// Обходим все элементы списка

const HashTable::Element * element = _ht.m_pData[ i ];

while ( element )

{

( * _f )( element->m_key, element->m_value );

element = element->m_pNext;

}

}

}

Наконец, составим основную часть программы в соответствии с условием:

#include "hash_table.hpp"

#include <iostream>

// Функция реакции на обход таблицы - печатает пару ключ-значение

void printKeyValue ( int _key, int _value )

{

std::cout << _key << ' ' << _value << std::endl;

}

// Основная программа

int main ()

{

// Создаем хэш-таблицу

HashTable * pHT = HashTableCreate( 10 );

// Цикл ввода данных

while ( true )

{

// Вводим очередное число

int value;

std::cin >> value;

// Прекращаем ввод при нажатии Ctrl+Z или в случае ошибки

if ( std::cin )

{

// Был ли данный ключ уже размещен в таблице ранее?

int count = HashTableGet( * pHT, value );

if ( count == -1 )

// Первое вхождение ключа

HashTableInsert( * pHT, value, 1 );

else

// Очередное вхождение ранее наблюдавшегося ключа

HashTableInsert( * pHT, value, count + 1 );

}

else

break;

}

// Инициируем обход таблицы с распечаткой пар ключ-значение

HashTableWalk( * pHT, & printKeyValue );

// Уничтожаем таблицу

HashTableDestroy( pHT );

}

Результат выполнения программы:

Соседние файлы в папке СТА (лекции+лабы)