
- •Очередь
- •Двусвязные списки
- •Пример использования стеков: постфиксная, префиксная и инфиксная записи
- •Бинарныедеревья
- •Общие деревья
- •Реализация деревьев
- •Представление графов
- •Задача нахождения кратчайшего пути
- •Нахождение кратчайших путей между парами вершин
- •Транзитивное замыкание
- •Нахождение центра ориентированного графа
- •Обход ориентированных графов
Пример использования стеков: постфиксная, префиксная и инфиксная записи
Префиксы «пре», «пост» и «ин» относятся к относительной позиции оператора по отношению к операндам. В префиксной записи операция предшествует операндам, в постфиксной следует за операндами, а в инфиксной записи операция разделяет два операнда.
А + В – инфиксная запись
А В + – постфиксная запись
+ А В – префиксная запись
Вычисление выражения А + В * С, записанное в стандартной инфиксной записи, требует знания того, какая из двух операций выполняется первой. В случае + и * мы знаем, что умножение выполняется раньше сложения (при отсутствии скобок). Следовательно, выражение А + В * С интерпретируется как А + (В * С). Говорят, что умножение имеет более высокий приоритет, чем сложение.
Предположим, что мы хотим записать выражение А + В * С в постфиксной записи. Учитывая правила приоритетности операций, мы сначала преобразуем часть выражения, которая вычисляется первой – умножение. Выполняя преобразование поэтапно, получим
А + (В * С) – скобки для выделения
А + (В С *) – преобразование операции умножения
А (В С *) + – преобразование операции сложения
А В С * + – постфиксная форма
Единственным правилом, используемым в процессе преобразования, является то, что операции с более высоким приоритетом преобразуются первыми, а после того, как операция преобразована к постфиксной форме, она рассматривается как один единый операнд. Рассмотрим теперь тот же пример, но приоритет выполнения операций изменим при помощи скобок:
(А + В) * С – инфиксная форма
(А В +) * С – преобразование операции сложения
(А В +) С * – преобразование операции умножения
А В + С * – постфиксная форма
Правила приоритетности для преобразования из инфиксной в префиксную форму аналогичны. Единственное отличие от постфиксного преобразования состоит в том, что операция помещается перед операндами, а не после них.
Примеры выражений в инфиксной, постфиксной и префиксной формах:
Инфиксное представление |
Постфиксное представление |
Префиксное представление |
A + B |
A B + |
+ A B |
A + B – C |
A B + C – |
– + A B C |
(A + B) * (C – D) |
A B + C D – * |
* + A B – C D |
A / B * C – D + E / F / (G + H) |
A B / C * D – E F / G H + / + |
+ – * / A B C D / E / F + G H |
((A + B) * C – (D – E)) * (F + G) |
A B + C * D E – – F G + * |
* – * + A B C – D E + F G |
A – B / (C * (D – E)) |
A B C D E – * / – |
– A / B * C – D E |
Алгоритм вычисления выражения, записанного в постфиксной форме:
Каждая операция в постфиксной строке ссылается к предшествующим двум операндам этой строки. Разумеется, одни из этих двух операндов может быть результатом выполнения предыдущей операции. Всякий раз, когда мы прочитываем операнд, мы записываем его в стек. Когда мы достигаем операции, то относящиеся к ней операнды будут двумя верхними элементами стека. Затем можно извлечь эти два операнда, осуществить над ними указанную операцию, и записать результат в стек. Тем самым он станет доступен в качестве операнда применительно к следующей операции.
Примервычисления выражения, заданного в постфиксной форме. Операндами являются цифры от 0 до 9. В программе используется описанный выше тип данныхstack.
#include <iostream.h>
#include <conio.h>
#include "stack.h"
intval(charc);//функция получения значения числа
main()
{
Element * stack;
char str[80];
int i, op1, op2, rez;
MakeNull (stack);
cin>>str;
for (i=0; str[i]; i++)
{
if(str[i]>='0' &&str[i]<='9')//если очередной символ - цифра
Push(val(str[i]),stack);//то она записывается в стек
else//иначе
{
op2 =Top(stack);//операнд2 берется с вершины стека
Pop(stack);//и из стека удаляется
op1 =Top(stack);//операнд 1 тоже берется из стека
Pop(stack);//и тоже из него удаляется
switch(str[i])// в зависимости от символа операции
{//выполняются арифметические действия
case '+' : {rez = op1 + op2; break;}
case '-' : {rez = op1 - op2; break;}
case '*' : {rez = op1 * op2; break;}
case '/' : {rez = op1 / op2; break;}
}
Push(rez,stack);//результат помещается в стек для использования
//его в качестве следующего операнда
}
}
cout<<rez<<'\n';
Pop (stack);//стек очищается
getch();
return 0;
}
int val (char c)
{
return c-48;
}