Знайомство з сортуванням файлів, Детальна інформація
Знайомство з сортуванням файлів
ЗНАЙОМСТВО З СОРТУВАННЯМ ФАЙЛІВ (на прикладі мови Паскаль)
1. Збалансоване злиття
У попередньому розділі ми розглядали сортування послідовностей, поданих масивами. Але в реальних задачах виникають послідовності, що зберігаються в файлах і не можуть уміщатися в оперативній пам'яті у вигляді масивів. Наприклад, у великому місті може бути кілька мільйонів абонентів телефонної мережі. Звичайно, для швидкого пошуку дані про абонентів мають бути відсортованими. Виникає задача сортування файлів за умови, що файли цілком не можна подавати в оперативній пам'яті. Таке сортування називається зовнішнім.
Один із найпростіших методів зовнішнього сортування має назву збалансованого злиття. Розглянемо його ідею.
Нехай F1 є файлом однотипних значень. Відрізком у ньому називається послідовність елементів, упоpядкована за зростанням значень, яка не є частиною іншої упорядкованої послідовності. Наприклад, у послідовності <2, 8, 3, 7, 6, 5, 3, 4, 1> є шість відрізків: <2, 8>, <3, 7>, <6>, <5>, <3, 4>, <1>.
Спочатку відpізки по черзі копіюються в допоміжні файли F3 і F4. Це первинне копіювання називається розподілом. У нашому прикладі маємо <2, 8, 6, 3, 4> в F3 і <3, 7, 5, 1> в F4.
Потім паpи перших, других тощо відpізків файлів F3 і F4 зливаються в довші відpізки та по черзі копіюються в F1 і допоміжний файл F2. У нашому прикладі маємо <2, 3, 7, 8, 1, 3, 4> в F1 та <5, 6> в F2. Цей крок називається злиттям. Потім паpи відpізків файлів F1 і F2 зливаються у файли F3 і F4 тощо доти, поки в результаті чергового злиття не утвориться єдиний відрізок.
Якщо перед черговим кроком злиття було M відрізків, то після нього їх стає не більше, ніж \xF0EB (M+1)/2\xF0FB . Звідси випливає, що таких кроків не більше \xF0E9 log2N\xF0F9 , де N – кількість елементів файла. Оскільки на кожному кроці злиття відбувається переписування всіх N елементів у інші файли, то складність такого алгоритму сортування можна оцінити як O(Nlog2N).
Можна збільшити кількість допоміжних файлів. Наприклад, якщо зливати не дві, а три послідовності, то кількість відрізків буде зменшуватися не менше, ніж утричі, тому кроків злиття буде не більше \xF0E9 log3N\xF0F9 , що в log23, тобто приблизно в півтора раза менше. Для цього будуть потрібні 5 допоміжних файлів.
Взагалі, використання 2k-1 допоміжних файлів вимагатиме не більше \xF0E9 logkN\xF0F9 кроків злиття. Отже, "розширення фронту" злиття є одним із джерел прискорення сортування.
З іншого боку, чим довшими будуть відрізки в початковому файлі, тим менше кроків злиття буде потрібно. Звідси створення початкового файла з якомога довшими відрізками також може суттєво прискорити сортування. Саме цю ідею ми розглянемо докладніше в наступному підрозділі.
2. Вибір із заміщенням
Тут ми опишемо створення файла з якомога довшими відрізками. Скористаємося методом, що належить Сьюворду та Думі, із удосконаленням Фрейзера та Уона (посилання див. у книзі [Кн3]). Цей метод грунтується на використанні дерева сортування.
Нехай початковий файл містить значення упорядкованого типу T. За цим файлом будується результатний файл із неспадаючими відрізками. При побудові використовується масив A із MX елементів. Нехай із початкового файла в цей масив прочитано n елементів, n\xF0A3 MX. Як і в алгоритмі пірамідального сортування (підр.17.4.2), будемо дивитися на масив як на дерево. Елемент масиву розглядається як вузол дерева, і кожний вузол, індекс якого k, є батьком вузлів із індексами 2k та 2k+1, де k
Нехай значення масиву розташовано таким чином, що значення кожного елемента-батька не більше значень елементів-синів, тобто за k=1, 2, … , n div 2 справджується
A[k] \xF0A3 A[2*k] та A[k] \xF0A3 A[2*k+1] (18.1)
Отже, перший елемент масиву має найменше значення, і його можна вивести в файл, у якому будуються неспадаючі відрізки. Після цього можна замістити це значення наступним із початкового файла та відновити властивість (18.1) у масиві. Звичайно, якщо нове значення менше виведеного, то його доведеться виводити вже в наступний відрізок результатного файла. В такому разі це значення не заміщає виведене, а запам'ятовується в додатковому сховищі. Коли в цьому сховищі накопичиться MX елементів, тоді виведемо елементи масиву A у порядку неспадання в результатний файл без їх заміщення новими. Після цього скопіюємо зміст сховища в масив, розташуємо значення в ньому згідно (18.1) і продовжимо виводити їх у порядку неспадання, заміщаючи їх значеннями з початкового файла.
Коли початковий файл буде прочитано, тоді ми виведемо зміст масиву в результатний файл і заповнимо масив із сховища. Після цього упорядкуємо його згідно (18.1) і знову виведемо його.
Уточнення наведеного опису почнемо з подання даних. Нехай тип елементів файла має ім'я T. Означимо типи файлів та масиву типу T:
type FoT=file of T; ArrT=array [1..MX] of T;
При сортуванні дуже часто виконується обмін місцями значень елементів масиву. Оскільки розміри елементів файла можуть бути великими, обмін місцями таких значень буде займати чимало часу. Спробуємо скоротити цей час, заплативши за це витратами пам'яті.
*
T
”
\x00D0
a
„
Tелементи масиву P своїми значеннями вказують на елементи масиву A. Властивість (18.1) відтворюється такою перестановкою значень масиву P, що за k=1, 2, … , n div 2
A[P[k]] \xF0A3 A[P[2*k]] та A[P[k]] \xF0A3 A[P[2*k+1]] (18.2)
Таким чином, виведення значення першого елемента масиву в результатний файл g задається як write(g, A[P[1]]). Замість обміну місцями значень у масиві A відбувається обмін значень у масиві P, заданий процедурою indswap:
1. Збалансоване злиття
У попередньому розділі ми розглядали сортування послідовностей, поданих масивами. Але в реальних задачах виникають послідовності, що зберігаються в файлах і не можуть уміщатися в оперативній пам'яті у вигляді масивів. Наприклад, у великому місті може бути кілька мільйонів абонентів телефонної мережі. Звичайно, для швидкого пошуку дані про абонентів мають бути відсортованими. Виникає задача сортування файлів за умови, що файли цілком не можна подавати в оперативній пам'яті. Таке сортування називається зовнішнім.
Один із найпростіших методів зовнішнього сортування має назву збалансованого злиття. Розглянемо його ідею.
Нехай F1 є файлом однотипних значень. Відрізком у ньому називається послідовність елементів, упоpядкована за зростанням значень, яка не є частиною іншої упорядкованої послідовності. Наприклад, у послідовності <2, 8, 3, 7, 6, 5, 3, 4, 1> є шість відрізків: <2, 8>, <3, 7>, <6>, <5>, <3, 4>, <1>.
Спочатку відpізки по черзі копіюються в допоміжні файли F3 і F4. Це первинне копіювання називається розподілом. У нашому прикладі маємо <2, 8, 6, 3, 4> в F3 і <3, 7, 5, 1> в F4.
Потім паpи перших, других тощо відpізків файлів F3 і F4 зливаються в довші відpізки та по черзі копіюються в F1 і допоміжний файл F2. У нашому прикладі маємо <2, 3, 7, 8, 1, 3, 4> в F1 та <5, 6> в F2. Цей крок називається злиттям. Потім паpи відpізків файлів F1 і F2 зливаються у файли F3 і F4 тощо доти, поки в результаті чергового злиття не утвориться єдиний відрізок.
Якщо перед черговим кроком злиття було M відрізків, то після нього їх стає не більше, ніж \xF0EB (M+1)/2\xF0FB . Звідси випливає, що таких кроків не більше \xF0E9 log2N\xF0F9 , де N – кількість елементів файла. Оскільки на кожному кроці злиття відбувається переписування всіх N елементів у інші файли, то складність такого алгоритму сортування можна оцінити як O(Nlog2N).
Можна збільшити кількість допоміжних файлів. Наприклад, якщо зливати не дві, а три послідовності, то кількість відрізків буде зменшуватися не менше, ніж утричі, тому кроків злиття буде не більше \xF0E9 log3N\xF0F9 , що в log23, тобто приблизно в півтора раза менше. Для цього будуть потрібні 5 допоміжних файлів.
Взагалі, використання 2k-1 допоміжних файлів вимагатиме не більше \xF0E9 logkN\xF0F9 кроків злиття. Отже, "розширення фронту" злиття є одним із джерел прискорення сортування.
З іншого боку, чим довшими будуть відрізки в початковому файлі, тим менше кроків злиття буде потрібно. Звідси створення початкового файла з якомога довшими відрізками також може суттєво прискорити сортування. Саме цю ідею ми розглянемо докладніше в наступному підрозділі.
2. Вибір із заміщенням
Тут ми опишемо створення файла з якомога довшими відрізками. Скористаємося методом, що належить Сьюворду та Думі, із удосконаленням Фрейзера та Уона (посилання див. у книзі [Кн3]). Цей метод грунтується на використанні дерева сортування.
Нехай початковий файл містить значення упорядкованого типу T. За цим файлом будується результатний файл із неспадаючими відрізками. При побудові використовується масив A із MX елементів. Нехай із початкового файла в цей масив прочитано n елементів, n\xF0A3 MX. Як і в алгоритмі пірамідального сортування (підр.17.4.2), будемо дивитися на масив як на дерево. Елемент масиву розглядається як вузол дерева, і кожний вузол, індекс якого k, є батьком вузлів із індексами 2k та 2k+1, де k
Нехай значення масиву розташовано таким чином, що значення кожного елемента-батька не більше значень елементів-синів, тобто за k=1, 2, … , n div 2 справджується
A[k] \xF0A3 A[2*k] та A[k] \xF0A3 A[2*k+1] (18.1)
Отже, перший елемент масиву має найменше значення, і його можна вивести в файл, у якому будуються неспадаючі відрізки. Після цього можна замістити це значення наступним із початкового файла та відновити властивість (18.1) у масиві. Звичайно, якщо нове значення менше виведеного, то його доведеться виводити вже в наступний відрізок результатного файла. В такому разі це значення не заміщає виведене, а запам'ятовується в додатковому сховищі. Коли в цьому сховищі накопичиться MX елементів, тоді виведемо елементи масиву A у порядку неспадання в результатний файл без їх заміщення новими. Після цього скопіюємо зміст сховища в масив, розташуємо значення в ньому згідно (18.1) і продовжимо виводити їх у порядку неспадання, заміщаючи їх значеннями з початкового файла.
Коли початковий файл буде прочитано, тоді ми виведемо зміст масиву в результатний файл і заповнимо масив із сховища. Після цього упорядкуємо його згідно (18.1) і знову виведемо його.
Уточнення наведеного опису почнемо з подання даних. Нехай тип елементів файла має ім'я T. Означимо типи файлів та масиву типу T:
type FoT=file of T; ArrT=array [1..MX] of T;
При сортуванні дуже часто виконується обмін місцями значень елементів масиву. Оскільки розміри елементів файла можуть бути великими, обмін місцями таких значень буде займати чимало часу. Спробуємо скоротити цей час, заплативши за це витратами пам'яті.
*
T
”
\x00D0
a
„
Tелементи масиву P своїми значеннями вказують на елементи масиву A. Властивість (18.1) відтворюється такою перестановкою значень масиву P, що за k=1, 2, … , n div 2
A[P[k]] \xF0A3 A[P[2*k]] та A[P[k]] \xF0A3 A[P[2*k+1]] (18.2)
Таким чином, виведення значення першого елемента масиву в результатний файл g задається як write(g, A[P[1]]). Замість обміну місцями значень у масиві A відбувається обмін значень у масиві P, заданий процедурою indswap:
The online video editor trusted by teams to make professional video in
minutes
© Referats, Inc · All rights reserved 2021