Формы представления алгебраических выражений



 

Рассмотрим в мкачестве примера использование стека для преобразования и вычисления алгебраических выражений.

Постфиксная запись представляет собой такую запись алгебраического выражения, в которой сначала записываются операнды, а затем – знак операции. Например, для выражения a + b * c постфиксная запись будет a b c * +. Здесь операндами операции * будут b и c (два ближайших операнда), а операндами операции + будут а и составной операнд b c *. Эта запись удобна тем, что она не требует скобок. Например, для выражения (a + b) * c постфиксная запись будет a b + c *. В этой записи не требуется ставить скобки для того, чтобы изменить порядок вычисления, зависящий от приоритета операций, как в исходном выражении. Поэтому постфиксная запись удобна для вычисления алгебраических выражений и широко применяется на практике.

В префиксной записи сначала наоборот записывается знак операции, а затем операнды. Например, для выражения a + b * c префиксная запись будет + a * b c. Префиксная запись также не требует расстановки скобок. Префиксную форму называют еще польской записью, а постфиксную – обратной польской записью.

Алгоритм Дейкстры перевода в постфиксную запись обрабатывает исходный массив лексем и строит новый массив из тех же лексем, расположенных в другом порядке. Кроме того, необходим еще стек – аналогичный массив, используемый для временного хранения операций.

Операции имеют разные приоритеты. Наименьший приоритет у операций ‘+’ и ‘-‘. Более высокий приоритет имеют операции ‘*’ и ‘/’. Еще более высокий приоритет у операции возведения в степень ‘^’. Самый высокий приоритет имеют операции операции, задаваемые функциями, такими как ‘sin‘, ‘cos’, ‘exp’. Заметим, что для этих операций требуется единственный операнд. Если операнд представляет собой выражение с другими знаками операций, то он должен заключаться в скобки.

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

  1. Константы и переменные кладутся в формируемую запись в порядке их появления в исходном массиве.
  2. При появлении операции в исходном массиве:

1) если в стеке нет операций или верхним элементом стека является открывающая скобка, операции кладётся в стек;

2) если новая операции имеет больший приоритет, чем верхняя операции в стеке, то новая операции кладётся в стек;

3) если новая операция левоассоциативная то есть вычисляется слева направо (‘+’, ‘-‘, ‘*’, ‘/’), то операции из стека большего или равного приоритета до ближайшей открывающей скобки или до конца стека перекладываются в формируемую запись, а новая операция кладётся в стек;

4) если новая операция правоассоциативная, то есть вычисляется справа налево (‘^’, ‘sin‘, ‘cos’, ‘exp’), то операции из стека большего приоритета до ближайшей открывающей скобки или до конца стека перекладываются в формируемую запись, а новая операция кладётся в стек.

  1. Открывающая скобка кладётся в стек.
  2. Закрывающая скобка выталкивает из стека в формируемую запись все операции до ближайшей открывающей скобки, открывающая скобка удаляется из стека.
  3. После того, как мы добрались до конца исходного выражения, операции, оставшиеся в стеке, перекладываются в формируемое выражение.

Примеры:

  1. a - b + c
Обрабатываемая лексема Результат Стек Пункт алгоритма
a a   1
- a - 2-1)
b a b - 1
+ a b - + 2-3)
c a b - c + 1
Конец a b - c +   5

После выталкивания операции из стека в результат при завершении работы порядок операций сменяется на противоположный.

  1. a + b - c * d
Обрабатываемая лексема Результат Стек Пункт алгоритма
a a   1
+ a + 2-1)
b a b + 1
- a b + - 2-3)
c a b + c - 1
* a b + c - * 2-2)
d a b + c d - * 1
Конец a b + c d * -   5

 

  1. a + b * c - d
Обрабатываемая лексема Результат Стек Пункт алгоритма
a a   1
+ a + 2-1)
b a b + 1
* a b + * 2-2)
c a b c + * 1
- a b c * + - 2-3)
d a b c * + d - 1
Конец a b c * + d -   5

 

  1. (a + b) * c
Обрабатываемая лексема Результат Стек Пункт алгоритма
(   ( 3
a a ( 1
+ a ( + 2-1)
b a b ( + 1
) a b +   4
* a b + * 2-1)
c a b + c * 1
Конец a b + c *   5

 

  1. (a + b * c) / 2
Обрабатываемая лексема Результат Стек Пункт алгоритма
(   ( 3
a a ( 1
+ a ( + 2-1)
b a b ( + 1
* a b ( + * 2-2)
c a b c ( + * 1
) a b c * +   4
/ a b c * + / 2-1)
2 a b c * + 2 / 1
Конец a b c * + 2 /   5

 

  1. (a * (b + c) + d) / 2
Обрабатываемая лексема Результат Стек Пункт алгоритма
(   ( 3
a a ( 1
* a ( * 2-1)
( a ( * ( 3
b a b ( * ( 1
+ a b ( * ( + 2-1)
c a b c ( * ( + 1
) a b c + ( * 4
+ a b c + * ( + 2-3)
d a b c + * d ( + 1
) a b c + * d +   4
/ a b c + * d + / 2-1)
2 a b c + * d + 2 / 1
Конец a b c + * d + 2 /   5

 

  1. a ^ b ^ c
Обрабатываемая лексема Результат Стек Пункт алгоритма
a a   1
^ a ^ 2-1)
b a b ^ 1
^ a b ^ ^ 2-4)
c a b c ^ ^ 1
Конец a b c ^ ^   5

 

  1. sin cos a
Обрабатываемая лексема Результат Стек Пункт алгоритма
sin   sin 1
cos   sin cos 3-4)
a a sin cos 1
Конец a cos sin   5

 

  1.  exp ( a * ln b)
Обрабатываемая лексема Результат Стек Пункт алгоритма
exp   exp 1
(   exp ( 3
a a exp ( 1
* a exp ( * 2-2)
ln a exp ( * ln 2-2)
b a b exp ( * ln 1
) a b ln * exp 4
Конец a b ln * exp   5

 

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

Примеры:

  1. Вычислим значение выражения a b c + * d + 2 / при а = 1, b = 2, c = 3, d = 4
Обрабатываемая лексема Стек
a 1
b 1 2
c 1 2 3
+ 1 5
* 5
d 5 4
+ 9
2 9 2
/ 4.5

 

  1. Вычислим значение выражения x x sin 2 * + при x = 3.14
Обрабатываемая лексема Стек
x 3.14
x 3.14 3.14
sin 3.14 0
2 3.14 0 2
* 3.14 0
+ 3.14

 

Очереди и их применение

 

Вторым распространенным типом линейных списков являются очереди. Это список типа FIFO (первым пришел – первым вышел) с двумя точками входа: начало и конец. Очередь пополняется с конца и продвигается с начала.

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

Аналогично стекам очереди могут быть организованы на основе массивов или динамических структур. При использовании массива начало очереди находится в первом элементе, а конец задается индексом и меняется при изменении очереди. Впрочем, возможно расположить очередь в массиве и в противоположном направлении.

Пусть очередь описана Var Och[1..N] of T, где T – тип элементов очереди. Конец очереди задан индексом Endo.

Постановка в очередь производится командами

Endo:= Endo+1;

Och[Endo]:=NewElement;

Продвижение очереди выполняется команками

 For I:=1 to Endo-1 do Och[I]:= Och[I+1];

Endo:= Endo-1;

Как и для стека, необходимо проверять выход за границы массива при постановке и непустоту очереди при удалении элементов.

При организации очереди на основе указателей используется следующее описание

Type

Ukaz=^Och;

Och=record

        Info: …;

        { поля информационной части элемента }

        Next: ukaz

      end;

Var

Bego, Endo: ukaz; { начало и конец очереди }

Выгодно указатели Next ориентировать в направлении от начала очереди к концу, а не наоборот. В этом случае постановка в очередь выполняется командами

New(Kon);

Endo^.Next:=Kon;

Kon^.Next:=Nil;

и далее присвоение значений информационным полям.


Дата добавления: 2018-11-24; просмотров: 1325; Мы поможем в написании вашей работы!

Поделиться с друзьями:






Мы поможем в написании ваших работ!