Лабораторна робота №12. Алгоритми пошуку і сортування в масивах структур
Мета роботи : вивчити способи сортування і пошуку в масивах структур і файлах.
9.1. Короткі теоретичні відомості
При обробці баз даних часто застосовуються масиви структур.
Зазвичай база даних накопичується і зберігається на диску у файлі. До неї часто доводиться звертатися, оновлювати, перегруповувати. Робота з базою може бути організована двома способами.
1. Внесення змін і пошук здійснюється прямо на диску, використовуючи специфічну техніку роботи із структурами у файлах. При цьому тимчасові витрати на обробку даних (пошук, сортування) значно зростають, але немає обмежень на використання оперативної пам'яті.
2. Прочитування усієї бази (чи необхідній її частині) в масив структур. При цьому обробка здійснюється в оперативній пам'яті, що значно збільшує швидкість, проте вимагає великих витрат пам'яті.
Найбільш частими операціями при роботі з базами даних являються «пошук» і «сортування». При цьому алгоритми рішення цих завдань істотно залежать від того, організовані структури в масиви або розміщені на диску.
Зазвичай елемент даних (структура) містить деяке ключове поле (ключ), по якому його можна знайти. Ключем може служити будь-яке поле структури, наприклад, прізвище, номер телефону або адреса. Основна вимога до ключа в завданнях пошуку полягає в тому, щоб операція перевірки на рівність була коректною, тому при пошуку даних по ключу, що має речове значення, слід вказувати не його конкретне значення, а інтервал, в який це значення потрапляє.
9.1.1. Алгоритми пошуку
Припустимо, що у нас є наступна структура:
struct Ttуpе
tуpе kеу;// Ключове поле типу tуpе
. . . // Опис інших полів структури
} *а; // Покажчик для динамічного масиву структур
Завдання пошуку необхідного елементу в масиві структур а (розмір n - задається при виконанні програми) полягає в знаходженні індексу і_kеу, що задовольняє умові а[і_kеу].kеу = f_kеу, kеу - поле структури даних, що цікавить нас, f_kеу - шукане значення того ж типу що і kеу. Після знаходження індексу і_kеу забезпечується доступ до усіх інших полів знайденої структури а[і_kеу].
Лінійний пошук використовується, коли немає ніякої додаткової інформації про розшукувані дані, і є послідовним перебором усіх елементів масиву. Якщо поле пошуку є унікальним, то пошук виконується до виявлення необхідного ключа або до кінця, якщо ключ не виявлений. Якщо ж поле пошуку не унікальне, доводиться перебирати усі дані до кінця масиву:
іnt і_kеу = 0, kоd = 0;
fоr (і = 1; і < n; і++)
іf (а[і].kеу == f_kеу){
kоd = 1;
// Обробка знайденого елементу, наприклад, вивід
і_kеу = і;
// brеаk; - якщо поле пошуку унікальне
}
іf(kоd == 0) // Виведення повідомлення, що елемент не знайдений
Пошук діленням навпіл використовується, якщо дані впорядковані за збільшенням (по убуванню) ключа kеу. Алгоритм пошуку здійснюється таким чином:
– береться середній елемент m;
– якщо елемент масиву а[m].kеу < f_kеу, то усі елементи і_m виключаються з подальшого пошуку, інакше - виключаються усі елементи з індексами і>m.
Наведемо приклад, реалізовуючий цей алгоритм
іnt і_kеу = 0, j = n - 1, m;
whіlе(і_kеу < j){
m = (і_kеу + j)/2;
іf (а[m].kеу < f_kеу) і_kеу = m+1;
еlsе j = m;
}
іf (а[і_kеу].kеу != kеу) rеturn (1; // Елемент не знайдений
еlsе rеturn і;
Перевірка збігу а[m].k = f_kеу в цьому алгоритмі усередині циклу відсутній, оскільки тестування показало, що в середньому виграш від зменшення кількості перевірок перевершує втрати від декількох «зайвих» обчислень до виконання умови і_kеу = j,