суббота, 27 января 2018 г.

10А электив. Стек

Задача. Вводится символьная строка, в которой записано некоторое (арифметическое) выражение, использующее скобки трех типов: (), [] и {}. Проверить, правильно ли расставлены скобки.
Например, выражение ()[{(){}}] - правильное, потому что каждой открывающей скобке соответствует закрывающая, и вложенность скобок не нарушается. Выражения
[()
[[[()
[()}

)(
([)]
неправильные. В первых трех есть непарные скобки, а в последних двух не соблюдается вложенность скобок.

Задачи, в которых важна вложенность объектов, удобно решать с помощью стека.

Уровень С. Реализуем стек для решения задачи в динамической памяти. Читаем про организацию стека в динамической памяти здесь:
http://pas1.ru/pointer
http://pas1.ru/dynamic
http://pas1.ru/pointernew
http://pas1.ru/pointeroperations
http://pas1.ru/dispose
http://pas1.ru/stack

Уровень В. Решаем задачу, организуя стек с помощью массива.
Алгоритм решения задачи.
Строка просматривается слева направо.
Если очередной символ - открывающая скобка, нужно поместить ее на вершину стека.
Если это закрывающая скобка, то проверяем, что лежит на вершине стека: если стек не пуст и на его вершине соответствующая открывающая скобка, то ее нужно просто удалить из стека; если стек пуст или на вершине лежит открывающая скобка другого типа, выражение неверное и нужно закончить просмотр.
Если в конце обработки строки стек остался не пуст, то выражение также неверное.
Советы по организации программы.
1) Стек сделать состоящим из переменных типа char:
Const
  N=255; 
Type
  stack=array[1..N] of char;
2) Ввести строковые константы L и R, которые будут содержать все вида открывающих и соответствующих закрывающих скобок:
Const
  L='([{';
  R=')]}';
3) В основной программе использовать переменные:
Var
  St : stack;      {стек}
  Top,i : byte;    {вершина стека и счетчик циклов}
  s : string;      {исходная строка}
  b : char;        {для удаления символа из стека}
  err : boolean;   {будет сигнализировать об ошибке}
4) Перебор символов строки:
For i:=1 to length(s) do
begin
  ...
end; 
5)Проверка того, что очередной символ - открывающая скобка:
  If pos(s[i],L)>0 then ...
   Проверка того, что очередной символ - закрывающая скобка: 
  If pos(s[i],R)>0 then ...
6) Проверка, что закрывающая скобка и символ на вершине стека - скобки одного типа:
  OutSt(b); 
  if pos(s[i],R)<>pos(b,L) then err:= true;
7) В начале программы переменной err присваиваем значение Fasle. При обнаружении ошибки записываем в нее значение True
  err:=True;
Если при обработке текущего символа обнаружено, что выражение неверное (значение переменной err - True), нужно закончить цикл досрочно с помощью оператора break.
  If err then break;
8) В конце программы остается вывести результат на экран:
  If Empty and not(err)
    then writeln('Выражение правильное')
    else writeln('Выражение неправильное');
9) Работа с самим стеком (описание, процедуры и функции, на примере стека из целых чисел ):
Type
  stack=array[1..N] of integer;    {тип данных "стек"}
Var
  St : stack;       {стек}

  top : integer;    {вершина стека}

Function Full:boolean;
begin
  Full := top=N;
end;

Function Empty:boolean;
begin
  Empty := top=0;
end;

Procedure AddSt(a:integer);
begin
  if not(full) then
    begin
      inc(top);
      st[top]:=a;
    end
  else
    writeln('Стек полон');
end;

Procedure OutSt(Var a:integer);
begin
  if not(Empty) then
    begin
      a:=st[top];
      dec(top);
    end
  else
    writeln('Стек пуст');
end;

Комментариев нет:

Отправить комментарий