C.Ю.Соловьев

Методические материалы
по курсу
"Алгоритмы и алгоритмические языки"

Программа курса
Программирование в машинных кодах
Примеры-1
Примеры-2
Пример "большой" программы
Нисходящее программирование
Ссылочные типы
Структуры данных
Таблицы
Хеш-таблицы
Очереди и стеки
Деревья поиска
AVL-деревья
Динамические страницы

Таблицы

(* Таблица - набор записей, каждая из которых однозначно *)
(*           определяется значением ключа.               *)
(* Соглашение. Будем считать, что ключ - целое число.    *)
 
type pElem = ^Elem;
      Elem = record Key : integer; ... end;

(* Операции : Поиск по ключу                        FindT *)
(*            Включение новой записи с ключом K     FormT *)
(*            Удаление записи с ключом K            KillT *)
(*          + Инициализация таблицы                       *)
(*          + Проверка наличия записей                    *)
(*        Подходы к программной реализации таблиц         *)
(* 1 Деревья поиска                                       *)
(* 2 Масивы: 2.1 Масивы записей >    array [...] of Elem; *)
(*           2.2 Масивы указателей на записи > рассмотрим *)
 
Const  So = 1024;                (* Max записей в таблице *)
  Var  Ko : integer;      (* Количество записей в таблице *)
        T : array [1..So] of pElem;            (* Таблица *)
(*      Ko:=0; - инициализация таблицы                    *)
(*      So-Ko  - запас для пополнения                     *)
(* Если 0 < Ko, то в таблице есть записи                  *)

(* Будем различать
(* таблицы с неупорядоченными записями: FindTno, FormTno, KillTno *)
(*    и                                                           *)
(* таблицы с   упорядоченными записями: FindTor, FormTor, KillTor *)

Таблицы с неупорядоченными записями

(* FindTno : поиск в таблице T с неупорядоченными записями *)
(*           записи со значением ключа K                   *)
(*       FindTno(K) = 0, если такой записи нет             *)
(* иначе FindTno(K) = номер искомой записи в таблице       *)
 
function FindTno(K : integer) : integer;
   var I : integer;
begin   for I:=1 to Ko do
        if T[I]^.Key = K then begin
           FindTno:=I;
           Exit
        end;
        FindTno:=0                  end;
(* FormTno : включить в таблицу T с неупорядоченными записями  *)
(*           запись с ключом K                                 *)
(* X:=FormTno(K);                                              *)
(* Если  X = 0, то отсутствие запаса не позволяет вып.операцию *)
(* Иначе
(* Если T[X] = nil, то для новой записи выделен номер X        *)
(* Если T[X]<> nil, то в таблице уже есть запись с ключом K    *)
 
function FormTno(K : integer) : integer;
   var M : integer;
begin   M:=FindTno(K);
             if  0 <  M  then FormTno:=M
        else if So <= Ko then FormTno:=0
        else begin
           Ko:=Ko+1;
           T[Ko]:=nil;        FormTno:=Ko
        end                           end;
 
(* KillTno : удалить из таблицы T с неупорядоченными записями  *)
(*           запись с ключом K                                 *)
 
procedure KillTno(K : integer);
   var N : integer;
begin   N:=FindTno(K);
        if 0 < N then begin
           Dispose(T[N]);
           T[N]:=T[Ko];
           Ko:=Ko-1
        end                end;

Таблицы с упорядоченными записями

(* В таблице T с упорядоченными записями выполняется свойство: *)
(* T[I]^.Key < T[J]^.Key,  если 1 <= I <= J <= Ko              *)
(* BFO : вспомогательная функция, которая                      *)
(*       по заданной таблице T с упорядоченными записями и     *)
(*       по заданному ключу K                                  *)
(*       вычисляет количество+1 записей в таблице,             *)
(*                                     ключи которых меньше K. *)
(* Если N = BFO(K) и 1 < N <= Ko,                              *)
(*                            то  T[N-1]^.Key < K <= T[N]^.Key *)
 
function BFO(K : integer) : integer;
   var HH,KK,M : integer;
begin   if Ko <   1       then begin BFO:=   1; Exit end;
        if K <= T[1]^.Key then begin BFO:=   1; Exit end;
        if T[Ko]^.Key < K then begin BFO:=Ko+1; Exit end;
        HH:=1;                        (* начало области поиска *)
        KK:=Ko;                       (* конец  области поиска *)
                 (* в обл.поиска: T[HH]^.Key < K <= T[KK]^.Key *)
        while 2 < KK-HH+1 do begin (* в обл. более 2-х записей *)
           M:=(HH+KK) div 2;                       (* середина *)
           if T[M]^.Key < K then HH:=M
                            else KK:=M
        end;
        BFO:=K;
end;
(* FindTor : поиск в таблице T с неупорядоченными записями *)
(*           записи со значением ключа K                   *)
(*       FindTor(K) = 0, если такой записи нет             *)
(* иначе FindTor(K) = номер искомой записи в таблице       *)
(* FindTor реализует метод дихотомического поиска          *)

function FindTor(K : integer) : integer;
   var N : integer;
begin   FindTor:=0;
        N:=BFO(K);
        if   N      <= Ko then
        if T[N]^.Key = K  then FindTor:=N   end;
(* FormTor : включить в таблицу T с упорядоченными записями    *)
(*           запись с ключом K                                 *)
(* X:=FormTor(K);                                              *)
(* Если  X = 0, то отсутствие запаса не позволяет вып.операцию *)
(* Иначе
(* Если T[X] = nil, то для новой записи выделен номер X        *)
(* Если T[X]<> nil, то в таблице уже есть запись с ключом K    *)
 
function FormTor(K : integer) : integer;
   var I,R : integer;
begin   R:=BFO(T,K);
        FormTor:=R;
        if (1 <= R) and (R <= Ko) then        (* K уже есть *)
        if       K   = T[R]^.Key  then Exit;
                        (* Включить новую запись на место R *)
        if Ko < So then begin           (* <=== Есть резерв *)
           for I:=Ko downto R do T[I+1]:=T[I];      (* Свиг *)
           T[R]:=nil;
           Ko:=Ko+1
        end        else FormTor:=0;     (* <=== Нет резерва *)
end;
(* KillTor : удалить из таблицы T с упорядоченными записями    *)
(*                                запись с ключом K            *)
 
procedure KillTor(K : integer);
   var I,N : integer;
begin   N:=FindTor(T,K);
        if 0 < N then begin
           Dispose(T[N]);
           for I:=N to Ko-1 do T[I]:=T[I+1];
           Ko:=Ko-1
        end                             end;

Вопросы?