
Метод інтерполяції
Я
кщо
немає ніякої додаткової інформації про
значення ключів, крім факту їхнього
впорядкування, то можна припустити, що
значення key
збільшуються від a[0]
до a[N-1]
більш-менш „рівномірно”. Це означає,
що значення середнього елементу a[N
/ 2] буде близьким до
середнього арифметичного між найбільшим
та найменшим значенням. Але, якщо шукане
значення key
відрізняється від вказаного, то є деякий
сенс для перевірки брати не середній
елемент, а „середньо-пропорційний”,
тобто такий, номер якого пропорційний
значенню key:
Програмна реалізація такого варіанту пошуку матиме вигляд:
int BinSearch(int *a, int key)
{
int b, e, i;
b = 0; e = N-1; // початкові значення меж
while ( b < e ) // цикл, поки інтервал пошуку не звузиться до 0
{
i = b + (key – a[b])*(e-b) / (a[e] – a[b]);
if ( a[i] == key )
return i; // ключ знайдений - повернення індексу
else
if ( a[i] < key )
b = i + 1; // пошук в правому підінтервалі
else
e = i - 1; // пошук в лівому підінтервалі
}
return -1; // ключ не знайдений
}
Вираз для поточного значення i одержано з пропорційності відрізків на рисунку:
В середньому цей алгоритм має працювати швидше за бінарний пошук, але у найгіршому випадку буде працювати набагато довше.
Метод „золотого перерізу”
Деякий
ефект дає використання так званого
„золотого перерізу”. Це число
,
що має властивість:
Доданій
корінь
і є золотим перерізом.
Згідно цього алгоритму відрізок b … e слід ділити не навпіл, як у бінарному алгоритмі, а на відрізки, пропорційні та 1, в залежності від того, до якого краю ближче key. Замість оператора
i = …;
у програму бінарного пошуку слід внести наступний фрагмент, попередньо визначивши константу Phi:
if a[e] - key < key - a[b]
i = b + (e - b) * (Phi - 1);
else
i = e - (e - b) * (Phi - 1) + 1;
Алгоритми пошуку послідовностей
Даний клас задача відноситься до задачі пошуку слів у тексті. Нехай масив a[N] вважається масивом символів останній елемент якого – 0:
char a[N];
у
якому слід знайти заданий рядок символів:
довжиною m.
Прямий алгоритм пошуку
Одним з найпростіших методів пошуку є послідовне порівняння першого символу s з символами масиву a. Якщо наявний збіг, тоді порівнюються другі, треті,... символи аж до повного збігу рядка s з частиною вектору такої ж довжини, або до незбігу у деякому символі. Тоді пошук продовжується з наступного символу масиву a та першого символу рядку s. Це визначається елементарною програмою:
i = 0; // номер символу масиву a
while (i < N - lenghts)
{
j = 0; // номер символу рядка s
while ((s[j] == a[i+j]) && (j<lenghts)
j++;
if (j==lenghts)
return i; // успіх
}
Якщо збіги відбуватимуться досить часто, то час роботи програми може бути досить значним.
Існує варіант удосконалення цього алгоритму – це починати пошук після часткового збігу не з наступного елементу масиву, а з символу, наступного після тих, що переглядалися, якщо у рядку s немає фрагментів, що повторюються.
j = 0; // j - номер символа у a
found = false;
while (!found)
{
i = 0; // i - номер символа у s
while ((s[i] == a[j]) && (s[i] != ‘/0’)
{
i++;
j++;
};
if (s[i] == ‘/0’
found = true;
else
j -= i-1;
};