
bffef1991ea7f03909065476d45bfaf4.ppt
- Количество слайдов: 7
Ассоциативные списки Поиск данных происходит не по индексу или положению объекта, а по его ассоциативной связи: public interface Map { // Доступ к объектам по ключу Object get(Object key); Object put(Object key, Object value); Object remove(Object key); // Размер ассоциативного списка int size(); boolean is. Empty(); // Проверка наличия ключей и значений boolean contains. Key(Object key); boolean contains. Value(Object value); // Очистка списка void clear(); } Другие классы и интерфейсы: Dictionary, Hash. Map, Hashtable
Способы реализации ассоциативных списков class Map. Container implements Map { // Структура, содержащая ассоциативную связь private static class Pair { Object key, value; Pair(Object key, Object value) { this. key = key; this. value = value; } } // Структура для поиска по ключу: // список, упорядоченный массив, дерево, . . . private Search. Struct container = new Search. Struct(); // Реализация операций: Object get(Object key) { // Поиск по ключу и возврат найденного значения } Object put(Object key, Object value) { Pair new. Pair = new Pair(key, value); // Вставка нового элемента с заданным ключом } }
Преимущества и недостатки различных структур данных для реализации ассоциативных списков Преимущества Упорядоченный массив Ø Ø Ø Список Ø Ø Ø Двоичное дерево Ø Ø Недостатки Логарифмическая скорость поиска Простота слияния Легкость итерации Ø Низкая скорость вставки и удаления элементов Удобство вставки и удаления элементов Простота слияния Легкость итерации 1. Низкая скорость поиска Логарифмическая скорость поиска Сравнительно быстрая вставка и удаление элементов Ø Ø Сложность итерации Слияние только поэлементное
Хеширование Идея: разделить все элементы на легко вычисляемые классы, и для каждого класса хранить свой собственный структурный объект. class Map. Container implements Map { // Параметры хеширования: final private static int HASH_MODULE = 128; private static int hash(Object obj) { return obj. hash. Code() % HASH_MODULE; } // Структура, содержащая ассоциативную связь private static class Pair { Object key, value; . . . } // массив структур: списков, упорядоченных массивов, деревьев, . . . private Search. Struct containers[] = new Search. Struct[HASH_MODULE]; // Реализация операций: Object get(Object key) { // Поиск по ключу и возврат найденного значения Search. Struct container = containers[hash(key)]; . . . } Object put(Object key, Object value) { Pair new. Pair = new Pair(key, value); // Вставка нового элемента с заданным ключом в containers[hash(key)] } }
Преимущества и недостатки хеш-таблиц Преимущества Ø Ø Возможность использования простых структур хранения Быстрый поиск при величине модуля, сравнимого с общим числом элементов Сравнительно быстрая вставка и удаление элементов Возможность работы с неупорядоченными ключами Недостатки Ø Ø Ø Итерация не в порядке возрастания ключей Слияние только поэлементное Необходимость «перехеширования» при увеличении числа хранимых объектов java. util. Hash. Map, java. util. Hashtable – варианты реализации этой идеи.
Один из вариантов реализации public class Hash. Dictionary { private int HASH_MODULE = 13; // Начальное значение хеш-модуля // Хеш-функция – скорректированная сумма кодов символов строки private int hash(String key) { int s = 0; for (int i = 0; i < key. length(); i++) { s += key. char. At(i) + i + 1; s %= HASH_MODULE; } return s; } // Узел списка – элемент контейнера private static class List. Node { String key; // ключ поиска Object obj; // ассоциированный объект List. Node next; // указатель на следующий элемент // Два варианта конструктора List. Node(String key, Object obj, List. Node next) { this. key = key; this. obj = obj; this. next = next; } List. Node(String key, Object obj) { this(key, obj, null); } } // Счетчик количества элементов private int count = 0; // Массив контейнеров-списков private List. Node[] container = new List. Node[HASH_MODULE];
Один из вариантов реализации (продолжение) public Object get(String key) { int hash = hash(key); // значение хеш-функции List. Node current = container[hash]; // для поиска элемента в контейнере for (current != null && !current. key. equals(key); current = current. next) ; return current == null ? null : current. obj; } public Object put(String key, Object value) { if (value == null) throw new Null. Pointer. Exception("Hash. Dictionary. put"); // value != null int hash = hash(key); // значение хеш-функции List. Node current = container[hash]; // для поиска элемента в контейнере for (current != null && !current. key. equals(key); current = current. next) ; if (current == null) { // ключ не найден – вставляем новый элемент списка container[hash] = new List. Node(key, value, container[hash]); if (++count > 2*HASH_MODULE) rehash(); // перехеширование, если необходимо! return null; } else { // ключ найден – заменяем ассоциированный объект Object tmp = current. obj; current. obj = value; return tmp; } } public Object remove(String key) { int hash = hash(key); // значение хеш-функции List. Node current = container[hash]; // для поиска элемента в контейнере List. Node prev = null; // предыдущий элемент списка (если есть) for (current = container[hash]; current != null && !current. key. equals(key); current = current. next) prev = current; if (current == null) { // ключ не найден – удалять нечего return null; } else { // ключ найден – удаляем элемент списка и возвращаем старое значение if (prev == null) container[hash] = current. next; else prev. next = current. next; count--; return current. obj; } } }