INTERFACE
Стек.
End
End
Then
Вставка заданного элемента в отсортированный 2-связный список.
End
End
Then
Begin
Удаление в 2-связном списке.
Создание 2-связного списка.
Type u = ^Uzl;
Uzl = Record
i :Integer;
L, R :u;
End;
Varh :u;
Procedure Create2List ( Var h :u; n :Word ); {n – количество узлов}
Var t :u; k :Word;
Begin New(h); h^.i := Random(50); h^.L := Nil; t := h; {создали новый узел}
For k:=1 To n-1 Do Begin
New ( t^.R ); и подключили его к R – ccылке предыдущего узла}
t^.R^.L := t; {в ссылочное поле нового узла записали L - ссылку }
t := t^.R; {указатель t переместили на новый узел }
t^.i := Random(50); { заполнили информационное поле нового узла }
End;
t^.R := Nil; { R - ссылка последнего узла равна Nil}
End;
ProcedureDel2List ( Var h :u; a :Integer );
Vart :u;
t := h;
While t <> Nil Do
Ift^.i = a
Ift = h Then Begint := t^.R; Dispose ( t^ .L ); {удаление спереди}
t^.L := Nil; h:=t; Exit;
Else Begint^.L^.R := t^.R; {удаление в середине}
t^.R^.L := t^.L;
Dispose( t ); Exit;
Elset := t^.R; { продвижение вдоль списка}
Writeln( ' нет такого элемента в списке ' );
End;
Procedure Ins2List ( Var h :u; a :Integer );
Vart, s :u;
Begin t := h; New (s ); s^.i := a;
Whilet <> Nil Do Цикл поиска и вставки узла в надлежащее место списка}
If a <= t^.i
Ift = h { если место вставки найдено }
Then Begins^.L := Nil; s^.R := h; { вставка в начало списка }
t^.L := s; h := s; Exit;
Else Begin s^.L := t^.L; t^.L := s; { вставка в середину списка }
s^.R := t; s^.L^.R := s; Exit;
Else If t^.R = Nil {если t указывает на последний элемент,
Then Break { то выход,
Else t := t^.R; иначе продвигаемся вперед}
{ конец цикла While }
If h = Nil
Then Begin h := s; s^.L := Nil; s^.R := Nil; End{ вставка в пустой список }
Else Begin s^.L := t; s^.R := Nil; t^.R := s; End; { вставка в конец списка }
End;
Замечания.
1. Обратите внимание, что Pascal допускает многократное применение операции ^(разыменование) в одном выражении, что позволяет, имея указатель на какой-либо узел, обращаться к полям нескольких соседних узлов, продвигаясь по ссылкам. Такая «косвенная адресация» к различным элементам списка является удобным средством обработки.
2. Часто для ускорения доступа к элементам 2-связного списка его снабжают еще одним указателем h2 на конец списка.
3. В операциях с 2-связными списками удается избавиться от рабочего указателя pна предыдущий элемент.
4. На основе рассмотренных операций над списками можно сделать простые и важные выводы. Если имеется последовательность элементов одного типа, то представление ее в виде списка особенно удобно в тех ситуациях, когда часто должны выполняться операции удаления и/или вставки произвольных элементов последовательности и когда используется прохождение всего списка. Массивы и файлы, безусловно, хуже списков, если рассматривать операции удаления и/или вставки произвольных элементов. Для массивов требуется смещение элементов, а для файлов — перезапись. Последовательная обработка массивов происходит несколько быстрее, чем последовательная обработка списков, а последовательная обработка файлов — медленнее. Массивы имеют определенные преимущества перед списками при произвольном доступе к элементам, особенно эффективен поиск определенного элемента в упорядоченном массиве. Этот тип поиска в случае списков относится к очень медленному и требует в среднем п/2 обращений к элементам списка и сравнений. Если ожидается, что элементы будут выбираться из середины или конца списка, то не требуется его последовательно просматривать, а нужно хранить несколько указателей на эти части списка.
Стек — частный случай линейного односвязного списка, для которого разрешено добавлять или удалять элементы только с одного конца списка, который называется вершиной стека (рис. 5.2). Такой принцип доступа к данным называется LIFO (Last In First Out – «последним пришел – первым вышел»). Голову списка в данном случае называют еще указателем стека (stack pointer –sp, однако в целях общности будем как и прежде придерживаться обозначения h).
Стек имеет важное значение для организации межмодульного взаимодействия, организации прерываний, рекурсивных вычислений и еще много других полезных применений, с которыми мы познакомимся в ходе изучения различных алгоритмов.
Удобно все операции со стеком оформить в виде процедур и функций и поместить в отдельный модуль. Ниже приводится пример такого модуля, в котором информационное поле элемента стека относится к символьному типу. Если нужен стек с другим типом элементов, то в этот модуль необходимо внести соответствующие изменения.
UNIT Stack;
Typeu = ^Uzl;
Uzl = Record
i :Char; {информационное поле символьного типа }
L :u;
End;
{ далее h – формальный параметр ! }
Procedure Push ( Var h :u; a :Char ); { включение в стек нового элемента.}
FunctionPop ( Var h :u ) :Char; {исключение элемента из стека }
FunctionEmpty ( h :u ) :Boolean; {функция «пустой» стек}
Function Top ( h :u ) :Char; {функция возвращает копию вершины}