
- •1.Этапы подготовки и решения задач на эвм.
- •1. Введение
- •2. Постановка задачи
- •3. Математическое описание задачи
- •4. Выбор и обоснование метода
- •5. Алгоритмизация вычислительного процесса
- •6. Составление программы
- •7. Отладка программы
- •8. Решение задачи на эвм и анализ результатов
- •2. Понятие подпрограммы, модуля и функции.
- •Условный оператор if
- •If (условие) оператор_1; else оператор_2;
- •If (условие) { оператор_1; оператор_2; … }
- •Оператор варианта switch
- •Цикл for
- •Цикл while
- •Цикл do while
- •Структурный тип данных – массив
- •Одномерные и двумерные массивы
- •Функция
- •Комбинированный тип данных – запись.
- •Работа с файлами
- •Указатели. Динамические переменные. Их использование
- •Применение связынных списков , очередей . И.Т.Д Очереди, стеки, связанные списки и деревья
- •Итеративные алгоритмы..
- •Невычислительные задачи
- •Последовательный поиск
- •Бинарный поиск
- •Метод поиска по бинарному дереву Теория
- •Вставка и удаление
- •Метод интерполяционного поиска Интерполяционный поиск
- •Метод поиска по бору . Алгоритм и его реализация
- •Добавление новой строки в бор:
- •Поиск строки в боре:
- •Реализация:
- •Методы хранения бора:
- •Сортировка простым выбором
- •Сортировка методом простой вставки
- •Метод сортировки бинарной вставкой
- •Метод сортировки стандартным обменом Стандартный обмен
- •Шейкерная сортировка
- •Метод сортировки Шелла.
Добавление новой строки в бор:
Пусть в начале добавления мы находимся в вершине с номером v = 0. Разберем 2 случая:
Мы пытаемся добавить s[i] букву и находимся в вершине v, а так же tree[v].num[s[i] - 'a'] не равно -1. Из этого следует, что переход для данной вершины по нужной нам букве уже существует, и достаточно просто изменить v = tree[v].num[s[i] - 'a'].
Мы пытаемся добавить s[i] букву и находимся в вершине v, однако теперь tree[v].num[s[i] - 'a'] равно -1. Значит еще не существует вершины в которую нужно перейти, а следовательно нужно ее добавить -увеличим глобальный счетчик cc и запишем в tree[v].num[s[i] - 'a'] новое значение cc, а также изменимv = cc.
После добавления последнего символа строки нам нужно tree[v].term приравнять к 1 (сказать, что в данной вершине одно из слов, добавленных в бор, закончилось) - это нам понадобится в поиске.
Поиск строки в боре:
При поиске в боре мы, можно сказать, просто спускаемся пока это возможно и можно выделить 2 случая:
Если в какой то момент мы находимся в вершине v и хотим перейти в след вершину по символу s[i] иtree[v].num[s[i] - 'a'] = -1, то просто прекращаем поиск и говорим, что такого слова в нашем дереве нет.
Слово, которое мы ищем кончилось, и мы находимся в вершине v. Если параметр term для данной вершины равен 1, то мы нашли слово, иначе нет.
Оценим ассимптотику приведенных выше алгоритмов: построение осуществляется за общую длину всех слов, которые мы добавляем, поиск получается в худшем случае за длину строки-запроса. Данные факты довольно легко понять, поняв сам алгоритм. Стоит также отметить, что в худшем случае бор может заниматьO(суммарная длина всех строк * размер алфавита) памяти.
Реализация:
?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
int cc = 0; // глобальны счетчик вершин
// добавление int v = 0; for (int i = 0; i < s.length(); i++){ int t = s[i]; if (tree[v].num[t] == -1){ cc++; tree[v].num[t] = cc; } v = tree[v].num[t]; } tree[v].term = 1;
// поиск int v = 0; for (int i = 0; i < s.length(); i++){ int t = s[i]; if (tree[v].num[t] == -1){ printf("Такого слова нет"); break; } v = tree[v].num[t]; } if (tree[v].term) printf("Такое слово есть в словаре"); else printf("Такого слова нет в словаре!"); |
Методы хранения бора:
Самый простой метод я уже описал, в нем для каждого состояния поиск нужного перехода осуществляется за O(1), однако мы используем довольно много лишней памяти, так как по сути всегда храним все возможные переходы.
Если размер возможного алфавита довольно велик и просто нет возможности хранить массив num[] для каждой вершины, то можно данный массив заменить на map <char, int> num. Тогда мы избавимся от проблемы недостатка памяти, но так как поиск и добавление в map происходит за O(log), то асимптотика домножится на log.
В предыдущих методах мы или проигрывали по памяти или проигрывали по времени, однако можно все сделать и без лишней памяти и без усложнения асимптотики, а именно завести один глобальный HashTable, в котором ключом будет хэш от пары номер вершины + номер символа перехода, а значением - номер вершины в которую мы попадем.