Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Нестеров.docx
Скачиваний:
3
Добавлен:
22.09.2019
Размер:
267.49 Кб
Скачать

24. Применение динамических структур данных. Проверка математического выражения на правильность расстановки скобок.

procedure CreateSt1;

begin

New(pTop1);

pTop1.next:=nil;

pTop1.d:='1';

end;

procedure Add1(x:String);

var pHelp:pEl;

begin

New(pHelp);

pHelp.next:=pTop1;

pHelp.d:=x;

pTop1:=pHelp;

end;

function Del1:String;

begin

If pTop1.next<>nil then

pTop1:=pTop1.next;

end;

procedure TForm1.Button1Click(Sender: TObject);

var i:integer;

begin

S:=Edit1.Text;

CreateSt1;

for i:=1 to length(S) do

begin

If S[i]='(' then

Add1(S[i]);

If S[i]=')' then

begin

If pTop1.next<>nil then

x:=Del1

else

begin

ShowMessage('There is a mistake');

exit;

end;

end;

end;

If pTop1.next<>nil then

ShowMessage('There is a mistake')

else

ShowMessage('No mistakes');

end;

end.

Вопрос 25.

Постфиксная, префиксная, инфиксная записи выражения.

Преобразование выражения из инфиксной в префиксную и постфиксную формы.

Обычные арифметические выражения, используемые в повседневной практике и содержащие скобки, называют инфиксными выражениями, поскольку знак операции располагается между операндами. Порядок выполнения действий в таких выражениях определяется старшинством операций и скобками. Вычисление и компиляция таких выражений подразумевает их предварительный анализ с целью выявления порядка выполнения операций. Существуют формы записи арифметических выражений без скобок, в которых порядок действий задается порядком знаков операций в выражении. Такие формы записи называются польской или бесскобочной записью. Польская запись может быть префиксной, в которой знак операции предшествует операндам, и постфиксной, в которой знак операции следует за операндом. Вычисление и компиляция бесскобочных выражений оказывается проще, чем выражений со скобками, поскольку операции должны выполняться в порядке описания и предварительный анализ не требуется.

Алгоритм перевода из инфиксной записи в префиксную:

Просматриваем строку справа налево. Операнды помещаем в первый стек, скобки и знаки операций во второй. Если очередной элемент открывающаяся скобка, то она заносится во второй стек, если этот элемент закрывающаяся скобка, то последовательно применяем операции из второго стека к операндам из первого. Результаты заносим в первый стек, до тех пор пока во втором стеке не встретим открывающуюся скобку.

Если очередной элемент знак операции и верхний элемент второго стека тоже знак операции, то необходимо сравнить приоритет:

- если приоритет добавляемой операции выше, то мы ее добавляем во второй стек

- если он ниже или равен, то последовательно применяем операции из второго стека к операндам из первого, до тех пор пока не найдем операцию с меньшим приоритетом (по алгоритму такое невозможно). Либо мы дойдем до открывающейся скобки, либо мы опустошим второй стек.

Если мы просмотрели всю строку и во втором стеке есть элементы, то последовательно извлекаем их и применяем к операндам из первого стека

А теперь разберем на простом примере алгоритм перевода алгебраического выражения из инфиксной в постфиксную форму. При разборе нам понадобится два стека. Первый стек - временный, в него мы будем помещать знаки операций (временный стек). А во втором стеке мы будем формировать выражение в постфиксной форме (основной стек).

  • Если символ - число (или переменная), помещаем его в основной стек.

  • Если символ - знак операции ('+', '-', '/', '*'), то проверяем приоритет данной операции. Операции умножения и деления имеют наивысший приоритет (3), операции сложения и вычитания имеют меньший приоритет (2), самый низкий приоритет (1) имеет открывающая скобка.

    • Если временный стек пуст, или находящиеся в нем символы (а находиться в нем могут только знаки операций и открывающая скобка) имеют меньший приоритет, чем приоритет текущего символа, то помещаем текущий символ во временный стек.

    • Если символ, находящийся на вершине стека имеет приоритет, больший или равный приоритету текущего символа, то извлекаем символы из стека в основной стек до тех пор, пока не встретим символ с меньшим приоритетом. Встретив символ с меньшим приоритетом, мы прекращаем извлекать символы из временного стека, и ни в коем случае не забываем добавить во временный стек текущий символ. Переходим к предыдущему пункту.

  • Если символ - открывающая скобка, то помещаем ее во временный стек.

  • Если символ - закрывающая скобка, то извлекаем символы из временного стека в основной до тех пор, пока не встретим во временном стеке открывающую скобку, которую просто уничтожаем. Закрывающая скобка также уничтожается.

  • Если вся входная строка разобрана, но во временном стеке еще остаются знаки операций, мы должны просто извлечь их в основной стек, начиная с последнего символа.

function Prior(x:String): integer;

begin

case x[1] of

'(',')': Result := 1;

'+', '-': Result := 2;

'*', '/': Result := 3

else Result:=0;

end;

end;

procedure InfToPost(S:String);

var i:integer;

begin

for i:=1 to length(S) do

begin

If S[i] in ['0'..'9'] then

Add1(S[i]);

If S[i] in ['+','-','/','*'] then

If pTop2=nil then

Add2(S[i])

else

begin

If Prior(S[i])>Prior(pTop2.d)then

Add2(S[i])

else

begin

Repeat

Add1(pTop2.d);

x:=Del2;

until (pTop2=nil)or(Prior(S[i])>Prior(pTop2.d));

Add2(S[i]);

end;

end;

If S[i]='(' then

Add2(S[i]);

If S[i]=')' then

begin

Repeat

If pTop2.d='(' then

begin

x:=Del2;

break;

end;

Add1(pTop2.d);

x:=Del2;

until pTop2.next=nil;

end;

end;

If pTop2.next<>nil then

while pTop2.next<>nil do

begin

Add1(pTop2.d);

x:=Del2;

end;

end;

procedure InfToPost(S:String);

var i:integer;

begin

for i:=length(S) downto 1 do

begin

If S[i] in ['0'..'9'] then

Add1(S[i]);

If S[i] in ['+','-','/','*'] then

If pTop2=nil then

Add2(S[i])

else

begin

If Prior(S[i])>Prior(pTop2.d)then

Add2(S[i])

else

begin

Repeat

Add1(pTop2.d);

x:=Del2;

until (pTop2=nil)or(Prior(S[i])>Prior(pTop2.d));

Add2(S[i]);

end;

end;

If S[i]=')' then

Add2(S[i]);

If S[i]='(' then

begin

Repeat

If pTop2.d=')' then

begin

x:=Del2;

break;

end;

Add1(pTop2.d);

x:=Del2;

until pTop2.next=nil;

end;

end;

If pTop2.next<>nil then

while pTop2.next<>nil do

begin

Add1(pTop2.d);

x:=Del2;

end;

end;

procedure TForm1.Button1Click(Sender: TObject);

begin

S:=Edit1.Text;

CreateSt1;

CreateSt2;

InfToPost(S);

pHelp:=pTop1;

while pHelp.next<>nil do

begin

S1:=S1+pHelp.d;

pHelp:=pHelp.next;

end;

Edit2.Text:=S1;

end;