1.7. ИСПОЛЬЗОВАНИЕ СЕЛЕКТОРОВ ПРЯМОГО ДОСТУПА
Одним из типичных случаев, когда требуется прямой доступ к частям выражения, являются алгоритмы, основанные на методе "разделяй и властвуй". Этот метод заключается в том, что исходная задача разбивается на подзадачи меньшего размера и решается для этих подзадач. Затем решение исходной задачи получается исходя из решений подзадач. Как правило, принцип "разделяй и властвуй" применяется совместно с принципом балансировки, гласящим, что исходную задачу следует разбивать на подзадачи примерно равного размера [АХУ 79].
В качестве классического примера рассмотрим задачу сортировки (т.е. упорядочения в порядке неубывания) множества целых чисел.Одним из способов решения этой задачи является сортировка слиянием [АХУ 79], когда исходное множество чисел
S разбивается на два непересекающихся множества S1 и S2 примерно равного размера. Затем S1 и S2 упорядочиваются независимо друг от друга. В результате получаются две упорядоченные последовательности чисел Q1 и Q2, которые соединяются (сливаются) в одну упорядоченную последовательность Q, которая и является решением исходной задачи. Теперь определим функцию MSort, которая получает на входе последовательность целых чисел, разбивает ее на две примерно равные части, сортирует их (обратившись к себе рекурсивно), а затем сливает получившиеся последовательности, обратившись к функции Merge.$func MSort eS = eS;
$func Merge (eX)(eY) = eZ;
MSort eS =
<Length eS> :: sLen,
{
<"<=" (sLen) (1)>
= eS;
= <Div sLen 2> :: sK,
<Left 0 sK eS> :: eS1,
<Middle sK 0 eS> :: eS2,
<Merge ( <MSort eS1> )( <MSort eS2> )>;
};
Теперь определим функцию Merge, которая получает на входе две упорядоченные последовательности и объединяет их в одну упорядоченную последовательность.
Merge (eX)(eY) =
{
eX :
= eY;
eY :
= eX;
(eX)(eY) : (sA eXRest)(sB eYRest)
= {
<"<=" (sA)(sB)>
= sA <Merge (eXRest)(eY)>;
= sB <Merge (eX)(eYRest)>;
};
};