Эффективные алгоритмы Хартиков Сергей Михайлович“Разработка эффективных алгоритмов” +


Эффективные алгоритмы Хартиков Сергей Михайлович

“Разработка эффективных алгоритмов” + “Рекурсивная реализация алгоритмов” + “Технология программирования” = “Эффективные алгоритмы”

Free Pascal www.freepascal.org

1 Byte 0 .. 255 1 ShortInt -128 .. +127 1 Boolean False(0) .. True(1) 2 Word 0 .. +65 535 2 Integer -32 768 .. +32 767 4 Longint - 2 * 109 .. + 2 * 109 4 Cardinal 0 .. 4 * 109 8 Int64 - 1019 .. + 1019 8 Qword 0 .. 2 * 1019 4/8 Real platform dependant 4 Single 1.5E-45 .. 3.4E38 (7-8 digits) 8 Double 5.0E-324 .. 1.7E308 (15-16 digits) 10 Extended 1.9E-4932 .. 1.1E4932 (19-20 digits) 8 Comp -2E64+1 .. 2E63-1 (19-20 digits) 8 Currency +/-922337203685477.5808/7

var x, y, z : Byte; a, b, c : Word; begin … z := x + y; c := a + b; …

Тип данных = Интерпретация содержимого памяти + Совокупность процедур обработки

var x, y : Byte; a, b, c : Longint; begin c := x * y + a * b; Вычисление выражений

var x, y : Byte; a, b, c : Longint; begin c := Longint(x) * Longint(y) + a * b; Приведение типов

Пример : Пользовательский числовой тип со знаком Задачи: сложение/вычитание - инициализация - ввод/вывод

Как делать? С “нуля” или воспользоваться существующими процедурами?

X = LX + Base * HX Y = Ly + Base * Hy Z = X + Y = = LX + Base * HX + Ly + Base * Hy = = (LX + Ly) + Base * (HX + Hy) Сложение в позиционной системе счисления

Вариант: type TLong = record L, H : Longint; end; { d = x + y + a + b } Sum(z, x, y); Sum(c, a, b); Sum(d, z, c);

Желательно: { d = x + y + a + b } d := Sum(x, Sum(y, Sum(a, b))); Как осуществить?
![var y : Longint; x : array[0 .. 3] of Byte; Физическое совмещение переменных var y : Longint; x : array[0 .. 3] of Byte; Физическое совмещение переменных](https://present5.com/customparser/7837152_134668288 --- alg-01.ppt/slide_14.jpg)
var y : Longint; x : array[0 .. 3] of Byte; Физическое совмещение переменных в памяти

Два способа представления строк: 1) Длина строки + массив символов (Char) 2) Массив символов + терминальный символ

program TLong; {ПОЛЬЗОВАТЕЛЬСКИЙ ЧИСЛОВОЙ ТИП СО ЗНАКОМ} const Base = 1000000000; Dcm = 9; Len = 8; type Long = String[Len]; Long1 = record Ln : Byte; L, H : Longint; end;

function Long2Int(X : Long) : Longint; var X1 : Long1 absolute X; begin Long2Int := X1.L + (Base * X1.H); end; function Int2Long(X : Longint) : Long; var Z1 : Long1; Z : Long absolute Z1; begin Z1.Ln := Len; Z1.L := X mod Base; Z1.H := X div Base; Int2Long := Z; end;

function Sum(X, Y : Long) : Long; var Z : Long; X1 : Long1 absolute X; Y1 : Long1 absolute Y; Z1 : Long1 absolute Z; begin Z1.Ln := Len; Z1.H := X1.H + Y1.H; Z1.L := X1.L + Y1.L; if Abs(Z1.L) >= Base then if Z1.L >= 0 then begin Dec(Z1.L, Base); Inc(Z1.H, 1); end else begin Inc(Z1.L, Base); Dec(Z1.H, 1); end;

if (Z1.H > 0) and (Z1.L < 0) then begin Inc(Z1.L, Base); Dec(Z1.H, 1); end else if (Z1.H < 0) and (Z1.L > 0) then begin Dec(Z1.L, Base); Inc(Z1.H, 1); end; Sum := Z; end;

function Sgn(X : Long) : Longint; var X1 : Long1 absolute X; begin Sgn := 1; if (X1.L < 0) or (X1.H < 0) then Sgn := - 1 else if (X1.L = 0) and (X1.H = 0) then Sgn := 0; end; function Inv(X : Long) : Long; var Z : Long; X1 : Long1 absolute X; Z1 : Long1 absolute Z; begin Z1.Ln := Len; Z1.H := - X1.H; Z1.L := - X1.L; Inv := Z; end;

function Cmp(X, Y : Long) : Longint; begin Cmp := Sgn(Sum(X, Inv(Y))); end; function Str2Long(S : String) : Long; var Z : Long; Z1 : Long1 absolute Z; Hs, Ls : String; Sign : Boolean; Code : Integer; begin Z1.Ln := Len; Z1.H := 0; Z1.L := 0; Sign := False; if Length(S) > 0 then if S[1] = '-' then begin Sign := True; Delete(S, 1, 1); end;

Hs := ''; Ls := ''; if Length(S) <= Dcm then Ls := S else begin Ls := Copy(S, Length(S) + 1 - Dcm, Dcm); Hs := Copy(S, 1, Length(S) - Dcm); end; Val(Ls, Z1.L, Code); Val(Hs, Z1.H, Code); if Sign then Z := Inv(Z); Str2Long := Z; end;

function Long2Str(X : Long) : String; var X1 : Long1 absolute X; Ls, Hs : String; begin Str(Abs(X1.L), Ls); while Length(Ls) < Dcm do Ls := '0' + Ls; Str(Abs(X1.H), Hs); Hs := Hs + Ls; while (Length(Hs) > 1) and (Hs[1] = '0') do Delete(Hs, 1, 1); if Sgn(X) < 0 then Hs := '-' + Hs; Long2Str := Hs; end;

Побочное действие функции var X, Y : Boolean; function DoIt : Boolean; begin Y := True; … end; … if X and DoIt then …

Внутреннее представление переменных var X, Y : Longint; function Factorial(N : Longint) : Longint; begin if N <= 1 then Factorial := 1 else Factorial := N * Factorial(N -1); end; procedure DoIt(A, B : Word; var Z : Longint); begin … end;

program Stroka; { ВАРИАНТ-А } const TStrSize = 9; type PStr = ^TStr; TStr = record S : String[TStrSize]; N : PStr; end; Динамические списки

function NewStr(S : String) : PStr; var P1, P2 : PStr; begin P1 := Nil; P2 := Nil; while S <> '' do begin if P2 = Nil then begin New(P2); P1 := P2; end else begin New(P2^.N); P2 := P2^.N; end; P2^.N := Nil; P2^.S := Copy(S, 1, TStrSize); Delete(S, 1, TStrSize); end; NewStr := P1; end;

function GetStr(P : PStr) : String; var S : String; begin S := ''; while P <> Nil do begin S := S + P^.S; P := P^.N; end; GetStr := S; end;

procedure DelStr(var P : PStr); var P1 : PStr; begin P1 := P; while P1 <> Nil do begin P1 := P1^.N; Dispose(P); P := P1; end; end; procedure PutStr(var P : PStr; S : String); begin DelStr(P); P := NewStr(S); end;

var P1 : PStr; begin P1 := Nil; PutStr(P1, ‘Пример строки текста'); WriteLn(GetStr(P1), '<'); PutStr(P1, ‘Другая строка'); WriteLn(GetStr(P1), '<'); PutStr(P1, ''); WriteLn(GetStr(P1), '<'); end.

program Stroka; { ВАРИАНТ-B } const TStrSize = 9; type PStr = ^TStr; TStr = record S : String[TStrSize]; N : PStr; end;

function GetStr(P : PStr) : String; var S : String; begin S := ''; while P <> Nil do begin S := S + P^.S; P := P^.N; end; GetStr := S; end;

procedure PutStr(var P : PStr; S : String); var P1, P2 : PStr; Empty : Boolean; begin P1 := P; Empty := (S = ''); if not Empty then if P1 = Nil then begin New(P1); P1^.N := Nil; P := P1; end; while S <> '' do begin P1^.S := Copy(S, 1, TStrSize); Delete(S, 1, TStrSize); if S <> '' then if P1^.N <> Nil then P1 := P1^.N else begin New(P1^.N); P1 := P1^.N; P1^.N := Nil; end; end;

P2 := P1; if Empty then P := Nil else if P2 <> Nil then begin P2 := P2^.N; P1^.N := Nil; P1 := P2; end; while P2 <> Nil do begin P2 := P2^.N; Dispose(P1); P1 := P2; end; end;

function NewStr(S : String) : PStr; var P : PStr; begin P := Nil; PutStr(P, S); NewStr := P; end; procedure DelStr(var P : PStr); begin PutStr(P, ''); end;

Кэш ( cache ) Алгоритмы вытеснения: LRU - Least Recently Used LFU - Least Frequently Used MRU - Most Recently Used ARC - Adaptive Replacement Cache Алгоритмы записи: WRITE-BACK – отложенная запись WRITE-THROUGH – сквозная запись

program LRU; { Least Recently Used } const cache_max = 128; type t_data = String; p_data = ^t_data; t_item = record tag : Longint; data : p_data; end; var cache : array[0 .. cache_max - 1] of t_item; size : Longint; f : file of t_data;

procedure search(id : Longint; get : Boolean; var x : t_data); var i, k : Longint; found : Boolean; item : t_item; begin k := 0; found := False; while (k < size) and not found do if Abs(cache[k].tag) = id then found := True else Inc(k); if k = cache_max then begin k := cache_max - 1; Dec(size); with cache[k] do if tag < 0 then begin Seek(f, Abs(tag)); Write(f, data^); end; end;
![if not found then begin Inc(size); with cache[k] do begin tag := id; if if not found then begin Inc(size); with cache[k] do begin tag := id; if](https://present5.com/customparser/7837152_134668288 --- alg-01.ppt/slide_39.jpg)
if not found then begin Inc(size); with cache[k] do begin tag := id; if get then begin Seek(f, tag); Read(f, data^); end; end; end; item := cache[k]; for i := k downto 1 do cache[i] := cache[i - 1]; cache[0] := item; with cache[0] do if get then x := data^ else begin data^ := x; tag := - Abs(tag); end; end;

var k : Longint; begin Assign(f, 'main.dat'); Reset(f); size := 0; for k := 0 to cache_max - 1 do with cache[k] do begin tag := 0; New(data); end; { ... }
![{ ... } for k := 0 to cache_max - 1 do with cache[k] { ... } for k := 0 to cache_max - 1 do with cache[k]](https://present5.com/customparser/7837152_134668288 --- alg-01.ppt/slide_41.jpg)
{ ... } for k := 0 to cache_max - 1 do with cache[k] do begin if tag < 0 then begin Seek(f, Abs(tag)); Write(f, data^); end; Dispose(data); end; Close(f); end.

program LFU; { Least Frequently Used } const cache_max = 128; freq_max = MaxLongint; type t_data = String; p_data = ^t_data; t_item = record tag, freq : Longint; data : p_data; end; var cache : array[- 1 .. cache_max - 1] of t_item; size : Longint; f : file of t_data;

procedure search(id : Longint; get : Boolean; var x : t_data); var i, k : Longint; found : Boolean; item : t_item; begin k := 0; found := False; while (k < size) and not found do if Abs(cache[k].tag) = id then found := True else Inc(k); if k = cache_max then begin k := cache_max - 1; Dec(size); with cache[k] do if tag < 0 then begin Seek(f, Abs(tag)); Write(f, data^); end; end;
![if not found then begin Inc(size); with cache[k] do begin tag := id; freq if not found then begin Inc(size); with cache[k] do begin tag := id; freq](https://present5.com/customparser/7837152_134668288 --- alg-01.ppt/slide_44.jpg)
if not found then begin Inc(size); with cache[k] do begin tag := id; freq := 0; if get then begin Seek(f, tag); Read(f, data^); end; end; end; Inc(cache[k].freq);
![item := cache[k]; while item.freq > cache[k - 1].freq do begin cache[k] := cache[k item := cache[k]; while item.freq > cache[k - 1].freq do begin cache[k] := cache[k](https://present5.com/customparser/7837152_134668288 --- alg-01.ppt/slide_45.jpg)
item := cache[k]; while item.freq > cache[k - 1].freq do begin cache[k] := cache[k - 1]; Dec(k); end; cache[k] := item; if cache[0].freq = freq_max then for i := 0 to size - 1 do cache[i].freq := cache[i].freq div 2; with cache[k] do if get then x := data^ else begin data^ := x; tag := - Abs(tag); end; end;
![var k : Longint; begin Assign(f, 'main.dat'); Reset(f); cache[- 1].freq := freq_max; size := var k : Longint; begin Assign(f, 'main.dat'); Reset(f); cache[- 1].freq := freq_max; size :=](https://present5.com/customparser/7837152_134668288 --- alg-01.ppt/slide_46.jpg)
var k : Longint; begin Assign(f, 'main.dat'); Reset(f); cache[- 1].freq := freq_max; size := 0; for k := 0 to cache_max - 1 do with cache[k] do begin tag := 0; New(data); end; { ... }
![{ ... } for k := 0 to cache_max - 1 do with cache[k] { ... } for k := 0 to cache_max - 1 do with cache[k]](https://present5.com/customparser/7837152_134668288 --- alg-01.ppt/slide_47.jpg)
{ ... } for k := 0 to cache_max - 1 do with cache[k] do begin if tag < 0 then begin Seek(f, Abs(tag)); Write(f, data^); end; Dispose(data); end; Close(f); end.
![Инкрементирование указателей var x : array [min .. max] of t_data; { ... } Инкрементирование указателей var x : array [min .. max] of t_data; { ... }](https://present5.com/customparser/7837152_134668288 --- alg-01.ppt/slide_48.jpg)
Инкрементирование указателей var x : array [min .. max] of t_data; { ... } for k := min to max – 1 do x[k] := x[k + 1]; Адрес элемента массива x[k] : base + (k – min) * SizeOf(t_data);
![var p1, p2 : ^t_data; { ... } p1 := @x[min]; p2 := p1; var p1, p2 : ^t_data; { ... } p1 := @x[min]; p2 := p1;](https://present5.com/customparser/7837152_134668288 --- alg-01.ppt/slide_49.jpg)
var p1, p2 : ^t_data; { ... } p1 := @x[min]; p2 := p1; Inc(p2); for k := min to max – 1 do begin p1^ := p2^; Inc(p1); Inc(p2); end;

Работа с битами AND – побитовое логическое умножение OR – побитовое логическое сложение NOT – побитовое логическое отрицание Операторы сдвига :


Пример : битовый массив const max_bit = 1024; type t_bits = array[0 .. max_bit div 8 - 1] of Byte;

procedure put_bit(var bits : t_bits; bit : Longint; value : Boolean); begin if value then bits[bit div 8] := bits[bit div 8] or (1 shl (bit mod 8)) else bits[bit div 8] := bits[bit div 8] and not (1 shl (bit mod 8)); end; function get_bit(var bits : t_bits; bit : Longint) : Boolean; begin get_bit := (bits[bit div 8] and (1 shl (bit mod 8))) <> 0; end;

Задачка из журнала «Квант» (раздел «Квант для младших школьников») В доме 64 квартиры. Дети играют во дворе в такую игру. Один из детей должен отгадать номер квартиры другого. Разрешается задавать только такие вопросы, на которые можно ответить либо «да», либо «нет». Вопрос: за какое минимальное число вопросов можно гарантированно отгадать номер квартиры?


Поиск в массиве (поиск делением пополам) program bin_seek; const length_a = 10000; type t_array = array[1 .. length_a] of Longint; var a : t_array;

function bin_search(x : Longint; var a : t_array) : Longint; var L, R, m : Longint; begin L := 1; R := length_a + 1; while L < R do begin m := (L + R) div 2; if a[m] < x then L := m + 1 else R := m; end; bin_search := L; end;

Инвариант: 1) выполняется в начале алгоритма; 2) для каждого блока верно то, что если он выполняется перед его началом, то он выполняется и после него; 3) в конце алгоритма выполнение инварианта означает достижение цели алгоритма.

function bin_search(x : Longint; var a : t_array) : Longint; var L, R, m : Longint; begin L := 1; R := length_a + 1; while L < R do begin m := (L + R) div 2; if a[m] < x then L := m + 1 else R := m; end; bin_search := L; end; Инвариант:

alg-01.ppt
- Количество слайдов: 59