- •Анализ алгоритмов (Лекции 2000)
- •Глава 1. Модели вычислений.
- •Глава 3. Перестановки как абстрактный тип данных
- •3.1 Представление перестановок в естественной форме.
- •Var a : array [1..N] of Boolean;
- •Var I, j, k, m:1..N; a:array[1..N] of Boolean;
- •If a[I] then
- •Var I,j:1..N; s:boolean:
- •Var I,j,k:1..N: a:array[1..N] of boolean;
- •If a[I] then
- •3.2 Представление перестановок в циклической форме.
- •Procedure trsl(var f: tpe; var g: tpc);
- •Var I : 1..N; s : Boolean;
- •If a[I] then
- •Procedure u1(var f : tpe; var g : tpk);
- •Var r : real;
- •3.3 Представление перестановок в виде таблицы инверсий.
- •Var I : 0..N; s : Boolean;
- •Var I, j, k : integer;
- •Var c : array [0..N] of 0..1;
- •X : array [1..N] of real;
- •Function ч3 (var r :tpi) : Boolean;
- •Var k, I, j, s, : integer;
- •3.4 Задача о складывании карт.
- •Var I,a,b : integer;
- •Var z:integer;
- •Глава 4. Генерация перестановок
- •4.1Генерация перестановок в лексикографическом порядке.
- •Var р : array [0..N] of 0..N; { текущая перестановка}
- •Var p : array [1..N] of 1..N;
- •Генерация перестановок за минимальное число транспозиций
- •Var I,k : integer;
- •Var p:array [0..N1] of 1..N1;
- •I,j,k,t: integer;
- •Глава 5. Генерация подмножеств множества
- •5.1Генерация подмножеств в лексикографическом порядке.
- •5.2 Генерация подмножеств за счет их минимального изменения.
- •Var s : array [1..N] of 0..1;
- •I : integer;
- •Var s : array [1..N] of 0..1;
- •I,j,k,p : integer;
- •Var t : array [0..N] of 1..N1; {стек}
- •Var t : array [0..N1] of 1..N2;
- •I,p : integer;
- •5.3Генерация мультимножеств.
- •Глава 6. Генерация k-подмножеств
- •Var s : array[1..K] of 1..N;
- •I,p : integer;
- •6.1Генерация k-подмножеств заменой одного элемента.
- •Var I : integer;
- •Var I,m,h:integer;
- •Упражнение. Выполните приведенный алгоритм для деревьв
- •В режиме неполного вычисления
- •Глава 8 Теорема о сложности рекурсивных программ
- •Глава 9 Производящие функции
5.1Генерация подмножеств в лексикографическом порядке.
Определение. Пусть A=(x1,…,xn) и B=(y1,…,yn), xi,yi{0,1}, 1in. Будем говорить, что множество А предшествует множеству B лексикографическом порядке ,если существует i, 1in, xi<yi и xj=yj для любого j, 1j<i; обозначим это А<B.
Упражнение. Пусть 0 a < b <2n, a, b - натуральные; представим a и b в двоичной системе с выписыванием всех n двоичных разрядов и пусть a = и b = . Доказать, что тогда (x1,...,xn) < (y1,...,yn).
Основываясь на результате упражнения, можно написать следующую программу генерации всех подмножеств данного множества в лексикографическом порядке.
program SET1(, output);
const n= ; n1= ; {n1=n+1}
var s : array [1..n1] of 0..1;
i,j : integer;
begin
for i:=1 to n1 do s[i]:=0;
while s[n1]=0 do
begin
for i:=1 to n do write(s[i]); writeln;
i:=1;
{**} while s[i]=1 do
begin s[i]:=0; i:=i+1 end;
{*} s[i]:=1
end
end.
Комментарий. Пусть множеству s соответствует число s, тогда множеству, следующему за s, соответствует число s+1.
Упражнения. 1.Доказать корректность алгоритма SET1.
-
Показать, что условие цикла {**} проверяется 2n+1-1 раз.
-
Определить вычислительную сложность алгоритма.
-
Написать программу генерации всех подмножеств в лексикографическом порядке, если s описано как SET OF 1..n.
Замечания. 1.Следует отметить, что в системе команд любой вычислительной машины имеются команды, выполняющие арифметическое сложение двоичных последовательностей определенной длин, таких, как 8 бит - 1 байт, 16 - 2 байта и тому подобное. Кроме того, часто имеются специальные программные конструкции (например, макрокоманды, выполняющие сложение более длинных двоичных последовательностей). Непосредственное применение таких команд в программе SET1 может существенно улучшить ее временные характеристики.
-
Для построения других алгоритмов генерации подмножеств, представляет интерес свойства последовательности значений переменной i перед исполнением оператора {*}. Заметим, что этот оператор {*} исполняется 2n раз, при этом последнее значение i=n+1 приводит к окончанию генерации всех подмножеств для множества из n-элементов. Пусть In обозначает эту последовательность значений переменной i за исключением последнего. In можно трактовать как последовательность номеров позиций младшей единицы в двоичном разложении чисел 1, 2, ..., 2n-1. По построению двоичной позиционной системы последовательность In удовлетворяет следующему рекурсивному определению
I1=1, In= In-1,n, In-1
(первый раз единица в n-ой позиции появляется для числа 2n-1, при этом во всех других позициях с 1-ой по (n-1)-ую значения становятся нулевыми, затем для чисел 2n-1+1,..., 2n-1 повторяется процесс заполнения единицами позиций с номерами меньшими n).
Упражнение. Доказать, что если In-1=i1, i2, ..., i, n>1, то In=1, i1+1, 1, i2+1, 1, ..., i+1, 1.
5.2 Генерация подмножеств за счет их минимального изменения.
Кроме генерации подмножеств данного множества в лексикографическом порядке весьма интересны схемы генерации при которых каждое последующее подмножество отличается от предыдущего вставкой или удалением одного элемента. Первым, естественно, рассмотрим вопрос, связанный с существованием подобных схем. Для этого вначале разберем частные генерации в зависимости от мощности базового множества, затем обобщим их. Считаем, что конкретные подмножества представлены в виде характеристических векторов.
Пусть n - мощность базового множества.
n = 1
1. (0); либо 1. (1);
2. (1). 2. (0).
n = 2
1. (0,0); либо ему симметричный 1. (0,0);
2. (1,0); 2. (0,1);
3. (1,1); 3. (1,1);
4. (0,1). 4. (1,0).
Других вариантов, начинающихся с пустого множества, нет!
n =3
-
(0,0,0,)
-
(1,0,0)
-
(1,1,0)
-
(0,1,0)
-
(0,1,1)
-
(1,1,1)
-
(1,0,1)
-
(0,0,1)
Упражнение. Построить другие варианты генерации подмножеств для n=3,начинающиеся с представления пустого множества.
Обобщим приведенные примеры:
Пусть C1; C2; ...; Ck-1; Ck содержит все k=2n двоичных представлений подмножеств множества из n элементов, причем каждое последующее подмножество отличается от предыдущего вставкой или удалением одного элемента. Тогда последовательность, генерирующая все подмножества множества из n+1 элемента может быть получена, например, так:
С10; C20; ...; CK-10; CK0; CK1; CK-11; ....;C21; C11.
Пример n=4
0 |
0 |
0 |
0 |
1 |
0 |
0 |
0 |
1 |
1 |
0 |
0 |
0 |
1 |
0 |
0 |
0 |
1 |
1 |
0 |
1 |
1 |
1 |
0 |
1 |
0 |
1 |
0 |
0 |
0 |
1 |
0
|
0 |
0 |
1 |
1 |
1 |
0 |
1 |
1 |
1 |
1 |
1 |
1 |
0 |
1 |
1 |
1 |
0 |
1 |
0 |
1 |
1 |
1 |
0 |
1 |
1 |
0 |
0 |
1 |
0 |
0 |
0 |
1 |
Рассмотрим последовательность номеров изменяемых разрядов при переходе от одного двоичного слово к другому. Обозначим ее Pn. Тогда эта последовательность удовлетворяет следующему рекурсивному определению
P1 = 1; Pn = Pn-1, n, P, n>1.
По индукции легко доказать, что для n>0 Pn = P.
Таким образом последовательность Pn совпадает с ранее определенной последовательностью In.
Пример. n = 4, P4 = I4 = 1, 2, 1, 3, 1, 2, 1, 4, 1, 2, 1, 3, 1, 2, 1.
Заметим, что значение m, 1mn, первый раз встречается как 2m-1-ый член Pn, затем повторяется через каждые 2m-1 членов последовательности.
Учитывая сказанное, можно построить на языке Паскаль следующий рекурсивный алгоритм:
program SET2 (,output);
const n= ;