
- •Cтруктуры данных и алгоритмы
- •Понятие структур данных и алгоритмов
- •1.2. Алгоритм Евклида
- •1.3. Классификация структур данных
- •1.4. Операции над структурами данных
- •1.5. Структурность данных и технология программирования
- •2. Простые структуры данных
- •2.1. Числовые типы
- •2.1.1. Целые типы
- •2.1.1.1. Перевод чисел из одной системы счисления в другую
- •2.1.2. Вещественные типы
- •2.1.3. Десятичные типы
- •2.1.4. Операции над числовыми типами
- •2.2. Битовые типы
- •2.3. Логический тип
- •2.4. Символьный тип
- •2.5. Перечислимый тип
- •2.6. Интервальный тип языкаPascal
- •2.7. Указатели
- •2.7.1. Физическая структура указателя
- •2.7.2. Представление указателей в языках программирования
- •2.7.3. Операции над указателями
- •3. Статические структуры данных
- •3.1. Векторы
- •3.2. Массивы
- •3.2.1. Логическая структура
- •3.2.2. Физическая структура
- •3.2.3. Операции
- •3.2.4. Адресация массивов с помощью векторов Айлиффа
- •3.2.5. Специальные массивы
- •3.3. Множества ( в языкеPascal )
- •3.3.1. Числовые множества
- •3.3.2. Символьные множества
- •3.3.3. Множество из элементов перечислимого типа
- •3.3.4. Множество от интервального типа
- •3.3.5. Операции над множествами
- •3.4. Записи
- •3.4.1. Логическое и машинное представление записей
- •3.4.2. Операции над записями
- •3.5. Записи с вариантами
- •3.6. Таблицы
- •3.7. Операции логического уровня над статическими структурами. Поиск
- •3.7.1. Последовательный или линейный поиск
- •3.7.2. Бинарный поиск
- •3.8. Операции логического уровня над статическими структурами. Сортировка
- •3.8.1. Сортировки выборкой
- •3.8.2. Сортировки включением
- •3.8.3. Сортировки распределением
- •3.9. Прямой доступ и хеширование
- •3.9.1. Таблицы прямого доступа
- •3.9.2. Таблицы со справочниками
- •3.9.3. Хешированные таблицы и функции хеширования
- •3.9.4. Проблема коллизий в хешированных таблицах
- •Библиографический Список
- •Оглавление
3.7. Операции логического уровня над статическими структурами. Поиск
В этом и следующих разделах представлен ряд алгоритмов поиска данных и сортировок, выполняемых на статических структурах данных, так как это характерные операции логического уровня для таких структур. Однако, те же операции и те же алгоритмы применимы и к данным, имеющим логическую структуру таблицы, но физически размещенным в динамической памяти или на внешней памяти, а также к логическим таблицам любого физического представления, обладающим изменчивостью.
Объективным критерием, позволяющим оценить эффективность того или иного алгоритма, является, так называемый, порядок алгоритма. Порядком алгоритма называется функция O(N), позволяющая оценить зависимость времени выполнения алгоритма от объема перерабатываемых данных (N - количество элементов в массиве или таблице). Эффективность алгоритма тем выше, чем меньше время его выполнения зависит от объема данных. Большинство алгоритмов с точки зрения порядка сводятся к трем основным типам:
степенные - O(Na);
линейные - O(N);
логарифмические - O(loga(N)).
Эффективность степенных алгоритмов обычно считается плохой, линейных - удовлетворительной, логарифмических - хорошей.
Аналитическое определение порядка алгоритма, хотя часто и сложно, но возможно в большинстве случаев. Возникает вопрос: зачем тогда нужно такое разнообразие алгоритмов, например сортировок, если есть возможность раз и навсегда определить алгоритм с наилучшим аналитическим показателем эффективности и оставить "право на жизнь" исключительно за ним? Ответ прост: в реальных задачах имеются ограничения, определяемые как логикой задачи, так и свойствами конкретной вычислительной среды, которые могут помогать или мешать программисту и которые могут существенно влиять на эффективность данной конкретной реализации алгоритма. Поэтому выбор того или иного алгоритма всегда остается за программистом.
В последующем изложении все описания алгоритмов даны для работы с таблицей, состоящей из записей R[1], R[2], ..., R[N] с ключами K[1], K[2], ..., K[N]. Во всех случаях N – количество элементов таблицы. Программные примеры для сокращения их объема работают с массивами целых чисел. Такой массив можно рассматривать как вырожденный случай таблицы, каждая запись которой состоит из единственного поля, которое является также и ключом. Во всех программных примерах следует считать уже определенными:
константу N- целое положительное число, число элементов в массиве;
константу EMPTY - целое число, признак "пусто" (EMPTY=-1);
массив – intmas[N]; сортируемые последовательности. В функцию будет передоваться указатель на первый элемент.
3.7.1. Последовательный или линейный поиск
Простейшим методом поиска элемента, находящегося в неупорядоченном наборе данных, по значению его ключа является последовательный просмотр каждого элемента набора, который продолжается до тех пор, пока не будет найден желаемый элемент. Если просмотрен весь набор, но элемент не найден, - значит, искомый ключ отсутствует в наборе.
Для последовательного поиска в среднем требуется (N+1)/2 сравнений. Таким образом, порядок алгоритма - линейный - O(N).
Программная иллюстрация линейного поиска в неупорядоченном массиве приведена в следующем примере, где mas- исходный массив, key - ключ, который ищется; функция возвращает индекс найденного элемента или EMPTY - если элемент отсутствует в массиве.
{===== Программный пример 3.4 =====}
int LinSearch( int* mas, int key )
{
for( int i=0; i<N; i++ ) // перебор элементов массива
if( mas[i] == key ) return i; // ключ найден,
// возврат индекса
return EMPTY; // просмотр завершен, но ключ не найден
}