рефераты конспекты курсовые дипломные лекции шпоры

Реферат Курсовая Конспект

Работа со словарем. Иоиск и вставка. Хеширование.

Работа со словарем. Иоиск и вставка. Хеширование. - раздел Образование, Основные операции при работе с деревьями   Довольно Часто Встречаются Ситуации, Когда Обработке Подлежат...

 

Довольно часто встречаются ситуации, когда обработке подлежат много маленьких строк — слов, которые надо сохранять в некоторой единой структуре — словаре. Сами слова не требуют для своего представления сложной структуры: для их представления вполне достаточно стандартных способов описания строк. Однако для словаря необходимо выбрать такое представление, которое бы обеспечило максимальную эффективность выполнения основной операции над словарем — поиска слова в словаре.

Самым простым представлением для словаря будет, конечно, массив слов. Для обеспечения эффективности поиска можно обеспечить упорядоченность элементов этого массива, тогда поиск слов можно производить с помощью алгоритма двоичного поиска, изученного ранее, который обеспечивает нахождение нужного слова среди множества из п слов за количество операций, пропорциональное log2 п. К сожалению, эффективность работы со словарем, организованным таким образом, резко снижается, когда требуется добавлять в него новые слова или удалять имеющиеся. Каждая вставка или удаление слова требуют сдвига в среднем около половины всех имеющихся в массиве слов. Кроме того, при вставке слов возникает проблема отведения новой памяти, если первоначально отведенной под словарь памяти не хватает для размещения новых элементов.

Одним из способов решения этой проблемы является использование так называемой функции расстановки или хеширования. Слово хеширование происходит от английского hash, означающего "крошить", "резать на кусочки", и отражает характер работы этой функции.

Основная идея применения функции расстановки состоит в следующем. Словарь будем представлять в виде массива слов, но помещать слова в него будем не в соответствии с алфавитным порядком, а в соответствии со значениями некоторой простой функции, вычисленной над словом. Такая функция — функция расстановки, — получая в качестве аргумента некоторое слово, выдает в качестве результата некоторое целое число — индекс в словаре, под которым следует хранить это слово. Если каждому слову будет соответствовать свое значение функции расстановки, то поиск в словаре становится ненужным. Вместо поиска осуществляется вычисление значения функции расстановки, после чего слово находится сразу же по вычисленному индексу.

К сожалению, на практике оказывается невозможным определить функцию расстановки так, чтобы каждому слову соответствовало свое уникальное значение индекса. Это приводит к тому, что два или более слов получают одно и то же значение функции расстановки. Говорят, что в этом случае происходит конфликт хеш-индексов (коллизия). Один из самых простых способов разрешения коллизий состоит в том, чтобы помещать слово, вызвавшее конфликт в один из соседних элементов массива. Тогда поиск и вставка новых слов будет производиться хотя и не за один шаг, но все же достаточно быстро.

Естественным требованием для функции расстановки будет требование простоты ее вычисления. Но это далеко не единственное, что требуется от хорошей функции расстановки. Прежде всего, надо обеспечить равномерное распределение вычисленных индексов слов в словаре.

Пусть функция code (с) по заданной букве выдает ее номер в латинском алфавите (если символ не является буквой латинского алфавита, то будем считать, что функция code возвращает значение 0). Вот как, например, может выглядеть эта функция:

 

intcode(char c)

{

returnstrchr("abcdefghijklmnopqrstuvwxyz", c) + 1;

}

На самом деле, на практике обычно просто используют внутренний код каждого символа, так что фактически в использовании функции code нет необходимости.

Далее эту функцию можно использовать как базовую для определения функции расстановки. Прежде всего, обеспечим зависимость значения функции расстановки от всех символов слова. Для этого сложим коды всех букв. Дополнительно, для того чтобы позиция буквы в слове также играла некоторую роль, будем добавлять к коду каждой буквы номер ее позиции. Далее решим, словарь какого размера нам потребуется. В конечном итоге значение функции хеширования должно получиться достаточно равномерно распределенным на множестве всех обрабатываемых слов, и попадать в диапазон [0, n-1], где п — размер словаря. Достаточно равномерное распределение получается, если вычислять индекс по формуле * Х+ Q) % n, где числа Р и Q — это некоторые простые числа, по порядку близкие к п, X— вычисленная сумма кодов букв слова, а символ % задает операцию вычисления остатка от целочисленного деления. Если, например, считать, что словаря в 1000 слов будет достаточно для наших целей, то можно выбрать для Р и Q значения 557 и 811, и тогда функция расстановки примет следующий вид:

inthash(conststring & str) {

intsum = 0;

for (int i = 0; i < str.length(); i++) {

sum += code(str[i]) + i;

}

return(557 * sum + 811)% 1000;

}

Теперь можно задать словарь, в котором будет храниться некоторое множество слов. Мы определим функцию добавления слова в словарь и функцию, выясняющую, содержит ли словарь заданное слово. В обеих функциях слово (или место для этого слова) ищется схожим образом: по слову вычисляется значение функции расстановки, затем происходит перебор позиций слов в массиве, предназначенном для их хранения, до тех пор, пока либо искомое слово не будет найдено, либо не встретится пустое значение.

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

 

Листинг : Определение простого словаря

– Конец работы –

Эта тема принадлежит разделу:

Основные операции при работе с деревьями

Основные операции при работе с деревьями... Определение глубины дерева... Обход дерева на заданную глубину включение нового значения в дерево...

Если Вам нужно дополнительный материал на эту тему, или Вы не нашли то, что искали, рекомендуем воспользоваться поиском по нашей базе работ: Работа со словарем. Иоиск и вставка. Хеширование.

Что будем делать с полученным материалом:

Если этот материал оказался полезным ля Вас, Вы можете сохранить его на свою страничку в социальных сетях:

Все темы данного раздела:

Оптимизация поиска в дереве
  Основное свойство дерева соответствует пословице " дальше в лес - больше дров" . Точнее, количество просматриваемых вершин от уровня к уровню растет в геометрической прогр

Нумерация вершин
  Способы обхода дерева.В деревьях обход вершин возможен только с использованием рекурсии, поэтому и их логическая нумерация производится согласно последовательности их рекурсивного о

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

Сбалансированные двоичные деревья
  После каждой операции изменения дерева можно проводить балансировку дерева, которая позволяет минимизировать его высоту. При этом поиск по двоичному дереву будет требовать минимальн

Преобразование лозы в сбалансированное двоичное дерево.
  Этот этап алгоритма более содержательный и поэтому менее очевидный. Поэтому сначала будет разобран простой пример, а потом будет дано его обобщение. Пусть есть лоза, котора

Алгоритмы представления графа
  При программировании задач обработки сетевых структур требуется решить вопрос о представлении графа структурами данных языка программирования. Выбор представления графа определяется

Файл setgraph.h
#include "graph.h" #include "set.h" // Определение класса для работы с множествами class SetGraph : public Graph { Set **graph; // Массив множеств дуг

Представление графа в виде матрицы смежности
  Еще один распространенный способ представления графа — это представление в виде матрицы смежности размером N * N (рис.1). B этой матрице в элементе с индексами (i,j) записывается ин

Файл MatrixGraph.cpp
#include "MatrixGraph.h"   // Реализация конструктора - заказ и инициализация памяти // под двумерный массив логических значений MatrixGraph::Matr

Представление графа в виде связанного списка
Списки вообще удобны тем, что могут содержать переменное количество элементов, при этом общий размер занимаемой ими памяти соответствует количеству элементов списка. Каждый элемент списка будет сод

Файл ListGraph.h
#include "graph.h" // Описание родительского класса   // Описание шаблона классов для представления // простых однонаправленных списков template &

Файл ListGraph.cpp
#include "ListGraph.h"   // Реализация операций над списком. // Добавление нового элемента в список template <class T> void List<

Представление графа в виде списка дуг
  Иногда используются и другие представления графов, например, для случая очень разреженных графов, когда при большом количестве N вершин графа число дуг существенно меньше NXN, напри

Файл ArcGraph.h
#include "graph.h" // Определение родительского класса // Описание класса для представления A-графа class ArcGraph : public Graph { // Дуга представлена элемент

Файл ArcGraph.cpp
«include "ArcGraph.h"   //Реализация операции добавления дуги void ArcGraph::addArc(int from, int to) { // Сначала проверяем правильность задания

Файл convert.срр
#include "SetGraph.h" #include "MatrixGraph.h" #include "ListGraph.h" #include "ArcGraph.h"   // Функция пр

Обходы в графах
  Как и в случае обхода деревьев, для графов существуют два основных класса обходов: обходы в глубину и обходы в ширину. Обходы в глубину пытаются каждый раз

Определение путей и контуров Эйлера
  Путь Эйлера проходит по каждому ребру в графе только один раз. Контур Эйлера проходит каждое ребро в графе тоже один раз, а также начинается и заканчивается в одной и той же вершине

Поиск кратчайших путей
Путем в графе называют чередующуюся последовательность вершин и дуг v1, e1, v2, e2,... vn-1 en-1, vn, в которой каждый элемент vi— вершина графа, а каждый элемент еi — дуга графа, ведущая из пре

Алгоритм Э. Дейкстры.
Опишем алгоритм нахождения такого пути при условии, что длины всех дуг неотрицательны. Этот алгоритм был предложен и опубликован Э. Дейкстрой (Е. W. Dijkstra), поэтому и носит его имя. Алг

Алгоритм Флойда — Уоршалла
Идея алгоритмом Флойда — Уоршалла, состоит в следующем. Будем рассматривать последовательность матриц смежности. В этой матрице элемент с индексами (i,j) равен +∞, если в графе нет ребра, вед

Определение остовных деревьев
Остовиым деревом (скелетом) неориентированного графа называется его подграф, не имеющий циклов и содержащий все вершины исходного графа. Так, например, для нагруженного графа, изображенно

Файл listgraph.h
// Класс ListGraph задает структуру L-графа class ListGraph {   // Массив списков дуг List<int> *graph; // Количество вершин графа i

Файл Arc.h
// Структура ребра для алгоритма Крускала: сравнение ребер // происходит по их весам   struct Arc { int from, to; double weight; Arc(int f

Файл listgraph.cpp
// Собственно алгоритм Крускала double ListGraph::minSkeleton( // Выходной поток для вывода результирующей информации: std::ostream & out, // Нагрузка на реб

Сортировка выбором
  Один из самых простых алгоритмов сортировки работает следующим образом. Сначала отыскивается наименьший элемент массива, затем он меняется местами с элементом, стоящим первым в сорт

Сортировка вставками
  Метод сортировки заключается в том, что отдельно анализируется каждый конкретный элемент, который затем помещается в надлежащее место среди других, уже отсортированных элементов. Сл

Пузырьковая сортировка
  Метод сортировки, который многие обычно осваивают раньше других из-за его исключительной простоты, называется пузырьковой сортировкой (bubble sort), в рамках которой выполняются сле

Быстрая сортировка
  Алгоритм быстрой сортировки обладает привлекательными особенностями: он принадлежит к категории обменных (in-place) сортировок (т.е., требует всего лишь небольшого вспомогательного

Сортировка слиянием
  Рассматривается сортировка слиянием (mergesort), которая является дополнением быстрой сортировки в том, что она состоит из двух рекурсивных вызовов с последующей процедурой слияния.

Пирамидальная сортировка
  Итак, мы постепенно переходим от более-менее простых к сложным, но эффективным методам. В качестве некоторой прелюдии к основному методу, рассмотрим перевернутую сортировку

Двоичный поиск
Если данные отсортированы, то может использоваться очень хороший метод поиска, названный двоичным поиском. При таком поиске используется метод "разделяй и властвуй". Сначала производится

Файл dictionary.h
// Класс, представляющий словарь в виде хеш-таблицы classHashDictionary { private: static const intP = 557;

Файл dictionary.cpp
// Реализация функций intHashDictionary::code(char c) { returnstrchr("abcdefghijklmnopqrstuvwxyz&

Файл "hashtable.h".
  // Класс, представляющий хеш-таблицу пар (ключ, значение), причем // ключом является строка, а значением может быть произвольный объект. //В таблице хранятся не са

Алгоритм прямого поиска подстроки в строке
  1. Установить i на начало строки S, т.е. i = 0. 2. Проверить, не вышло ли i + M за границу N строки S. Если да, то алгоритм

Хотите получать на электронную почту самые свежие новости?
Education Insider Sample
Подпишитесь на Нашу рассылку
Наша политика приватности обеспечивает 100% безопасность и анонимность Ваших E-Mail
Реклама
Соответствующий теме материал
  • Похожее
  • Популярное
  • Облако тегов
  • Здесь
  • Временно
  • Пусто
Теги