Міністерство освіти і науки, молоді та спорту України
Національний університет „Львівська політехніка”
Кафедра ЕОМ
Розрахункова робота
з дисципліни: “Обчислювальний практикум”
Зміст
Теоретична частина…………………..…………………………………………..3
Моделювання АТД…………..…………………………………………………...7
Застосування АТД до розв’язку практичних задач………………..………….16
Завдання 1……………………………………………………………………16
Завдання 2……………………………………………………………………17
Завдання 3……………………………………………………………………18
Завдання 4……………………………………………………………………19
Додаток 1……..……………………………………………………………….…20
Завдання 1……………………………………………………………………20
Завдання 2……………………………………………………………………23
Завдання 3……………………………………………………………………24
Завдання 4……………………………………………………………………26
Додаток 2…………………..……………………………………………….……33
Завдання 1……………………………………………………………………34
Завдання 2……………………………………………………………………35
Завдання 3……………………………………………………………………36
Завдання 4……………………………………………………………………38
Теоретична частина
Абстрактний тип даних (АТД) - це тип даних, який надає для роботи з елементами цього типу певний набір функцій, а також можливість створювати елементи цього типу за допомогою спеціальних функцій. Вся внутрішня структура такого типу захована від розробника програмного забезпечення - в цьому і полягає суть абстракції. Абстрактний тип даних визначає набір функцій, незалежних від конкретної реалізації типу, для оперування його значеннями. Конкретні реалізації АТД називаються структурами даних.
В програмуванні абстрактні типи даних звичайно представляються у вигляді інтерфейсів, які приховують відповідні реалізації типів. Програмісти працюють з абстрактними типами даних виключно через їх інтерфейси, оскільки реалізація може в майбутньому змінитися. Такий підхід відповідає принципу інкапсуляції в об'єктно-орієнтованому програмуванні. Сильною стороною цієї методики є саме приховування реалізації. Раз зовні опублікований тільки інтерфейс, то поки структура даних підтримує цей інтерфейс, всі програми, що працюють із заданою структурою абстрактним типом даних, будуть продовжувати працювати. Розробники структур даних стараються, не змінюючи зовнішнього інтерфейсу і семантики функцій, поступово допрацьовувати реалізації, покращуючи алгоритми по швидкості, надійності і використовуваної пам'яті.
Різниця між абстрактними типами даних і структурами даних, які реалізують абстрактні типи, можна пояснити на наступному прикладі. Абстрактний тип даних список може бути реалізований за допомогою масиву або лінійного списку, з використанням різних методів динамічного виділення пам'яті. Однак кожна реалізація визначає один і той же набір функцій, який повинен працювати однаково (по результату, а не по швидкості) для всіх реалізацій.
Абстрактні типи даних дозволяють досягти модульності програмних продуктів і мати кілька альтернативних взаємозамінних реалізацій окремого модуля.
Приклади АТД:
Список
Стек
Чергу
Асоціативний масив
Черга з пріоритетом
Стек
Стек в інформатиці та програмуванні — різновид лінійного списку, структура даних, яка працює за принципом (дисципліною) «останнім прийшов — першим пішов» (LIFO, англ. last in, first out). Всі операції (наприклад, видалення елементу) в стеку можна проводити тільки з одним елементом, який знаходиться на верхівці стеку та був введений в стек останнім.
Стек можна розглядати як певну аналогію до стопки тарілок, з якої можна взяти верхню, і на яку можна покласти верхню тарілку (інша назва стеку — «магазин», за аналогією з принципом роботи магазину в автоматичній зброї)
Операції зі стеком
Виконання операції push.
push ("заштовхнути елемент"): елемент додається в стек та розміщується в його верхівці. Розмір стеку збільшується на одиницю. При перевищенні розміру стека граничної величини, відбувається переповнення стека (англ. stack overflow)
pop ("виштовхнути елемент"): отримує елемент з верхівки стеку. При цьому він видаляється зі стеку і його місце в верхівці стеку займає наступний за ним відповідно до правила LIFO, а розмір стеку зменшується на одиницю. При намаганні "виштовхнути" елемент з вже пустого стеку, відбувається ситуація "незаповнення" стеку (англ. stack underflow)
Кожна з цих операцій зі стеком виконується за фіксований час O(1) і не залежить від розміру стеку.
Додаткові операції (присутні не у всіх реалізаціях стеку):
isEmpty: перевірка наявності елементів в стеку; результат: істина (true), коли стек порожній.
isFull: перевірка заповненості стека. Результат: істина, коли додавання нового елементу неможливе.
clear: звільнити стек (видалити усі елементи).
top: отримати верхній елемент (без виштовхування).
size: отримати розмір (кількість елементів) стека.
swap: поміняти два верхніх елементи місцями.
Організація в пам'яті комп'ютера
Стек може бути організований як масив або множина комірок в певній області комп'ютера з додатковим зберіганням ще й вказівника на верхівку стека. Заштовхування першого елемента в стек збільшує адресу вказівника, виштовхування елементу зменшує її. Таким чином, адреса вказівника завжди відповідає комірці масиву, в якій зараз знаходиться верхівка стеку.Багато процесорів ЕОМ мають спеціалізовані регістри, які використовуються як вказівники на верхівку стеку, або використовують деякі з регістрів загального вжитку для цієї спеціальної функції в певних режимах адресації пам'яті.
Черга
Черга (англ. queue) в програмуванні — динамічна структура даних, що працює за принципом «перший прийшов — перший пішов» (англ. FIFO — first in, first out). У черги є голова (англ. head) та хвіст (англ. tail). Елемент, що додається до черги, опиняється в її хвості. Елемент, що видаляється з черги, знаходиться в її голові.
Така черга повністю аналогічна звичній «базарній» черзі, в якій хто перший встав в неї, той першим буде обслуженим.
Основні операції з чергою
англ. enqueue — "поставити в чергу". Операція додавання елемента в "хвіст" черги. При цьому довжина черги збільшується на одиницю. Якщо відбувається намагання додати елемент у вже заповнену чергу, відбувається її переповнення (англ. queue overflow).
dequeue — "отримання з черги". Операція, яка повертає елемент з голови та видаляє його з черги, таким чином встановлюючи голову на наступний за видаленим елемент та зменшуючи довжину на одиницю. При намаганні видалити елемент з пустої черги, виникає ситуація "незаповнення" (англ. queue underflow).
Список
Список - це абстрактний тип даних , що представляє собою упорядкований набір значень, в якому деяке значення може зустрічатися більше одного разу. Примірник списку є комп'ютерна реалізація математичного поняття кінцевої послідовності - кортежу. Примірники значень , що знаходяться в списку , називаються елементами списку ( англ. item , entry або element ) ; якщо значення зустрічається кілька разів , кожне входження вважається окремим елементом .
Терміном список також називається кілька конкретних структур даних , що застосовуються при реалізації абстрактних списків , особливо зв'язкових списків.
Властивості списку
Розмір списку - кількість елементів у ньому , виключаючи останній « нульовий» елемент, що є за визначенням порожнім списком .
Тип елементів - тип якого набувають усі елементи.
Відсортованість - список може бути відсортований відповідно з деякими критеріями сортування ( наприклад , за зростанням цілочисельних значень , якщо список складається з цілих чисел).
Можливості доступу - деякі списки в залежності від реалізації можуть забезпечувати програміста селекторами для доступу безпосередньо до заданого за номером елементу .
Порівнянність - списки можна порівнювати один з одним на відповідність , причому залежно від реалізації операція порівняння списків може використовувати різні технології
Дерево
Де́рево (англ. tree) — в інформатиці та програмуванні одна з найпоширеніших структур даних. Формально дерево визначається як скінченна множина Т з однієї або більше вершин (вузлів, nodes), яке задовольняє наступним вимогам:
існує один відокремлений вузол — корінь (root) дерева
інші вузли (за виключенням кореня) розподілені серед m ≥ 0 непересічних множин T1…Tm і кожна з цих множин в свою чергу є деревом. Дерева T1…Tm мають назву піддерев (subtrees) даного кореня.
Властивості
З визначення випливає, що кожна вершина є в свою чергу коренем деякого піддерева. Кількість піддерев вершини має назву ступеня (degree) цієї вершини. Вершина ступеню нуль має назву кінцевої (terminal) або листа (leaf). Некінцева вершина також має назву вершини розгалуження (branch node).
Нехай x — довільна вершина дерева з коренем r. Тоді існує єдиний шлях з r до x. Усі вершини на цьому шляху називаються предками (ancestors) x; якщо деяка вершина y є предком x, то x називається нащадком (descendant) y. Нащадки та предки вершини x, що не збігаються з нею самою, називаються власними нащадками та предками. Кожну вершину x, в свою чергу, можна розглядати як корінь деякого піддерева, елементами якого є вершини-нащадки x.
Якщо вершини x є предком y та не існує вершин поміж ними (тобто x та y з'єднані одним ребром), а також існують предки для x (тобто x не є коренем), то вершина x називається батьком (parent) до y, а y — дитиною (child) x. Коренева вершина єдина не має батьків.
Вершини, що мають спільного батька, називаються братами (siblings). Вершини, що мають дітей, називаються внутрішніми (internal). Глибиною вершини x називається довжина шляху від кореня до цієї вершини. Максимальна глибина вершин дерева називається висотою.
Якщо існує відносний порядок на піддеревах T1…Tm, то таке дерево називається впорядкованим (ordered tree) або пласким (plane tree).
Лісом (англ. forest) називають множину дерев, які не перетинаються.
Найчастіше дерева в інформатиці зображують з коренем, який знаходиться зверху (говорять, що дерево в інформатиці «росте вниз»).
Важливим окремим випадком кореневих дерев є бінарні дерева, які широко застосовуються в програмуванні і визначаються як множина вершин, яка має виокремлений корінь та два піддерева (праве та ліве), що не перетинаються, або є пустою множиною вершин (на відміну від звичайного дерева, яке не може бути пустим).
Операції над деревом
Важливими операціями на деревах є:
обхід вершин в різному порядку
перенумерація вершин
пошук елемента
додавання елемента у визначене місце в дереві
видалення елемента
видалення цілого фрагмента дерева
додавання цілого фрагмента дерева
трансформації (повороти) фрагментів дерева
знаходження кореня для будь-якої вершини
Найбільшого розповсюдження ці структури даних набули в тих задачах, де необхідне маніпулювання з ієрархічними даними, ефективний пошук в даних, їхнє структуроване зберігання та модифікація.
Моделювання АТД
Завдання 1:
Змоделювати абстрактний тип даних (АТД) , Оформити АТД у вигляді класа. Переписати основні операції роботи з АТД і продемонструвати їх застосування при додаванні та вилученні елементів з АТД.
Алгоритм розв’язання задачі:
#include <string>
#include<iostream>
using namespace std;
template<class T>
class Stack
{
public:
Stack():tail(0), head(0)
{
}
~Stack()
{
while(head)
{
tail=head->next;
delete head;
head=tail;
}
}
void push(T val)
{
Node* Temp;
Temp=new Node;
Temp->elem=val;
if(tail==0)
{
tail=Temp;
}
else
{
Temp->next=tail;
tail=Temp;
}
}
T top()
{
if(tail==0)
{
throw std::string("Stack is empty!");
}
return tail->elem;
}
void pop()
{
if(tail==0)
{
throw std::string("Stack is empty!");
}
Node* delptr=tail;
tail=tail->next;
delete delptr;
}
void print()
{
if(tail==0)
{
throw std::string("Stack is empty!");
}
for(Node* ptr=tail; ptr!=0; ptr=ptr->next)
{
std::cout<<ptr->elem<<' ';
}
std::cout<<'\n';
}
private:
struct Node
{
Node():elem(0), next(0)
{
}
Node* next;
T elem;
};
Node* head;
Node* tail;
};
Завдання 2:
Змоделювати абстрактний тип даних (АТД) , Оформити АТД у вигляді класа. Переписати основні операції роботи з АТД і продемонструвати їх застосування при додаванні та вилученні елементів з АТД.
Алгоритм розв’язання задачі:
#pragma once
#include<cassert>
#include<stdio.h>
#include<tchar.h>
#include<iostream>
const int M = 100;
template<class Item>
class queue
{
private:
Item INFO[M];
int count;
public:
queue( );
void pop( );
void push(const Item& entry);
bool empty( ) const { return (count == 0); }
Item front( ) const;
int size( ) const { return count; }
void show();
void muve();
bool full(){return (INFO[M-1] == M-1);};
void wipe_out();
bool same();
};
template<class Item>
queue<Item>::queue( )
{
count = 0;
INFO[0] = 1;
INFO[M-1] = 0;
}
template<class Item>
Item queue<Item>::front( ) const
{
assert(!empty( ));
return INFO[1];
}
template<class Item>
void queue<Item>::pop( )
{
muve();
count--;
}
template<class Item>
void queue<Item>::push(const Item& entry)
{
assert(!(count > M - 1));
++count;
INFO[++INFO[M-1]] = entry;
}
template<class Item>
void queue<Item>::show()
{
std::cout <<"QUENE: ";
for(int i = INFO[0]; i < INFO[M-1]+1; i++){
std::cout << INFO[i] <<" " ;
}
std::cout << std::endl;
}
template<class Item>
void queue<Item>::muve()
{
for(int i = INFO[0]; i < INFO[M-1]; i++){
INFO[i] = INFO[i+1];
}
--INFO[M-1];
}
template<class Item>
void queue<Item>::wipe_out()
{
for (int i=0; i<count; i++)
{
muve();
}
count = 0;
}
template<class Item>
bool queue<Item>::same()
{
bool b = false;
for (int i=0; i<count-1; i++)
if (INFO[i]==INFO[i+1]) { b = true; }
return b;
}
Завдання 3:
Змоделювати абстрактний тип даних (АТД) Оформити АТД у вигляді класа. Переписати основні операції роботи з АТД і продемонструвати їх застосування при додаванні та вилученні елементів з АТД.
Алгоритм розв’язання задачі:
#include <iostream>
using namespace std;
class list
{
public:
list(){head = new (node); head->next = NULL;}
~list(){destroy(); delete head;}
void push_back(int);
void push_front(int);
void pop_back();
void pop_front();
void print();
void print_reverse();
void destroy();
private:
struct node
{
int data;
node* next;
node* prev;
};
node* head;
};
void list::push_back(int el)
{
node* p,*p1;
p = head;
while(p->next != NULL)
{p = p->next;}
p1 = new (node);
p1->data = el;
p1->next = NULL;
p1->prev = p;
p->next = p1;
}
void list::print()
{
node* p;
p = head->next;
while(p != NULL)
{
cout<<(p->data)<<" ";
p = p->next;
}
}
void list::push_front(int el)
{
node* p;
p = new (node);
p->data = el;
if(head->next == NULL)
{
p->next = head->next;
head->next = p;
p->prev = head;
}
else
{
p->next = head->next;
head->next->prev = p;
head->next = p;
p->prev = head;
}
}
void list::print_reverse()
{
node* p;
p = head;
while(p->next != NULL)
{p = p->next;}
while(p != head)
{
cout<<(p->data)<<" ";
p = p->prev;
}
}
void list::destroy()
{
node* p,* p1;
p = head;
p1 = p->next;
while(p1 != NULL)
{
p = p1;
p1 = p1->next;
delete p;
}
}
void list::pop_back()
{
node* p,* p1;
p = head;
p1 = p->next;
while(p1->next != NULL)
{
p = p1;
p1 = p1->next;
}
p->next = NULL;
delete p1;
}
void list::pop_front()
{
node* p;
p = head->next;
head->next = p->next;
p->next->prev = head;
delete p;
}
Завдання 4:
Змоделювати абстрактний тип даних (АТД) Оформити АТД у вигляді класа. Переписати основні операції роботи з АТД і продемонструвати їх застосування при додаванні та вилученні елементів з АТД.
Алгоритм розв’язання задачі:
#include <iostream>
#include <string.h>
#include <ctype.h>
using namespace std;
const int MAX = 50 ;
class infix
{
private :
char target[MAX],stack[MAX];
char *s,*t;
int top,l;
public :
infix();
void setexpr(char *str);
void push (char c);
char pop();
void convert();
int priority (char c);
void show();
} ;
infix::infix()
{
top=-1;
strcpy(target,"");
strcpy(stack,"");
l=0;
}
void infix::setexpr(char *str)
{
s=str;
strrev(s);
l=strlen(s);
*(target+l)='\0';
t=target+(l-1);
}
void infix::push(char c)
{
if (top==MAX-1)
cout<<"\nСтек повний!\n";
else
{
top++ ;
stack[top] = c ;
}
}
char infix::pop()
{
if (top==-1)
{
cout<<"Стек пустий!\n";
return -1;
}
else
{
char item=stack[top] ;
top--;
return item;
}
}
void infix::convert()
{
char opr;
while (*s)
{
if (*s==' '||*s=='\t')
{
s++;
continue;
}
if (isdigit(*s)||isalpha(*s))
{
while (isdigit(*s)||isalpha(*s))
{
*t=*s;
s++;
t--;
}
}
if (*s==')')
{
push(*s);
s++;
}
if (*s=='*'||*s=='+'||*s=='/'||*s=='%'||*s=='-'||*s=='$')
{
if (top!=-1)
{
opr=pop();
while(priority(opr)>priority(*s))
{
*t=opr;
t--;
opr=pop();
}
push(opr);
push(*s);
}
else
push(*s);
s++;
}
if (*s=='(')
{
opr=pop();
while ((opr )!=')')
{
*t=opr;
t--;
opr=pop();
}
s++;
}
}
while (top!=-1)
{
opr=pop();
*t=opr;
t--;
}
t++;
}
int infix::priority(char c)
{
if (c=='$')
return 3;
if (c=='*'||c=='/'||c=='%')
return 2;
else
{
if (c=='+'||c=='-')
return 1 ;
else
return 0;
}
}
void infix::show()
{
while(*t)
{
cout<<*t<<" ";
t++;
}
}
void main()
{
setlocale (LC_ALL,".1251");
char expr[MAX];
infix q;
cout<<"\nВведiть вираз в iнфiкснiй формi: ";
cin.getline(expr,MAX);
q.setexpr(expr);
q.convert();
cout<<"Вираз в префiкснiй формi: ";
q.show();
cout<<endl;
system("pause");
}
Застосування АТД до розв’язку прикладних задач
Завдання 1:
Перетворити вираз з інфіксної форми запису без дужок в постфіксну форму.
Код програми та блок-схема алгоритму наведені у додатку 1 та додатку 2 відповідно.
Результат виконання програми
/
Завдання 2:
2. Автостоянка має одну полосу, на якій може бути розмiщено до 10 автомобiлiв. Машини в'їжджають з пiвденного кiнця стоянки i від'їжджають з пiвнiчного. Якщо автомобiль власника, що прийшов на стоянку забрати його, не розташований пiвнiчнiше за всі решту, то всi автомобiлi, що стоять пiвнiчнiше його, виїжджають iз зупинки, потiм виїжджає його машина і всі машини повертаються в початковому порядку. Якщо машина залишає гараж, то всi машини розташованi пiвденнiше, перемiщаються вперед на стiльки позицій, скiльки є вiльних мiсць в пiвнiчнiй частинi. Написати програму зчитування групи рядків, кожний з яких мiстить літеру "A" для прибуття i літеру "D" для вiдправлення, а також номер машини. Машини прибувають i вiдправляються в порядку, що задає цей список рядків. Програма має видавати повiдомлення при кожному прибутті або вiдправленні машини. При прибутті машини в ньому повинно говоритись, чи є на стоянці вiльне мiсце. Якщо вiльне мiсце вiдсутнє, машина чекає до тих пiр, поки воно не звiльниться, або до моменту зчитування рядка, що повідомляє про вiдправлення цього автомобiля. Якщо з'являється вiльне мiсце, повинно видаватись iнше повiдомлення. При вiдправленнi автомобiля повiдомлення повинно мiстити в собi кiлькiсть перемiщень машини в серединi стоянки (включаючи її вiдправлення, але не прибуття; це число рiвне 0, якщо машина була вiдправлена під час очiкування вільного місця).
Код програми та блок-схема алгоритму наведені у додатку 1 та додатку 2 відповідно.
Результат виконання програми:
/
Завдання 3:
2. Многочлен виду , де представити у вигляді зв’язаного списку в якому кожний вузол має три поля: одне – для
коефіцієнта Сi , друге – для показника степеня ni , третє – для вказівника на наступний вузол списку. Для описаного представлення многочленів програмно реалізувати таку операцію: Множення многочлена на одночлен.
Алгоритм виконання завдання наведений у додатку 1.
Результат виконання програми:
Завдання 4:
4.2. Глосарій або предметний покажчик підручника складається з впорядкованих по алфавіту основних термінів, кожен з яких супроводжується впорядкованою за зростанням послідовністю номерів сторінок, де він зустрічається, і множиною підтермінів. Підтерміни виводяться на наступних за основним терміном рядках, вони дещо зсунуті вправо відносно основного терміна і впорядковані по алфавіту всередині основного терміна. Кожен підтермін супроводжується впорядкованою за зростанням послідовністю номерів сторінок, де він зустрічається.
Розробити структуру даних для представлення такого предметного покажчика і написати програму для зображення предметного покажчика по вхідних даних, що зберігаються у текстовому файлі.
Кожний вхідний рядок починається або з символу М (основний термін), або з символу S (підтермін). Рядок з символом М містить основний термін, за котрим слідують номери сторінок, на котрих зустрічається основний термін. Рядок з символом S будується аналогічно, за винятком того, що він містить не основний термін, а підтермін. Вхідні рядки з’являються у будь-якому порядку. Єдина умова: кожен підтермін вважається підтерміном найближчого попереднього основного терміна. Для одного основного терміна або підтерміна може бути декілька вхідних рядків (всі номери сторінок, що з’являються для конкретного терміна у будь-якому рядку, повинні бути надруковані разом з цим терміном).
Код програми та блок-схема алгоритму наведені у додатку 1 та додатку 2 відповідно.
Результат виконання програми:
/
Додаток 1
Завдання 1
Код програми
infix_to_postfix.h
#ifndef _INFIX_TO_POSTFIX_H_
#define _INFIX_TO_POSTFIX_H_
#include <stack>
#include <string>
using std::string; // включення типу string з простору імен std;
using std::stack;
class InfixToPostfix
{
private:
string input; // зберігає вхідний інфіксний рядок
stack<char> st; // об"єкт типу Stack
bool isOperator(const char ch) const; // визначає чи заданий символ оператор
int GetPriority(const char ch) const; // повертає пріорітет заданого символа
public:
InfixToPostfix(); // конструктор за замовчуванням
InfixToPostfix(const string &str); // конструктор з параметрами
~InfixToPostfix(); // деструктор
void AddInfixString(const string &str); // додавання інфіксного рядка
string TranslateToPostfix(); // перевід рядка з інфіксної до постфіксної форми запису
};
#endif /* _INFIX_TO_POSTFIX_H_ */
infix_to_postfix.cpp
#include "infix_to_postfix.h"
InfixToPostfix::InfixToPostfix() // конструктор за замовчуванням
{
}
InfixToPostfix::InfixToPostfix(const string &str) // конструктор з параметрами
{
input = str; // копіюєм вхідний рядок
}
InfixToPostfix::~InfixToPostfix() // деструктор
{
}
bool InfixToPostfix::isOperator(const char ch) const
{
if (ch == '+' || ch == '-' || ch == '*' || ch == '/') // якщо вхідний символ оператор
return true;
else // іншому випадку
return false;
}
int InfixToPostfix::GetPriority(const char ch) const
{
if (ch == '+' || ch == '-')
return 2;
if (ch == '*' || ch == '/')
return 3;
else
return 0;
}
void InfixToPostfix::AddInfixString(const string &str)
{
input = str; // копіюєм вхідний рядок
return;
}
string InfixToPostfix::TranslateToPostfix()
{
string output; // об"єкт вихідного рядка
for (unsigned i = 0; i < input.size(); ++i) // прохід по всьому вхідному рядку
{
if (isOperator(input[i])) // якщо це оператор
{
if (st.empty()) // якщо стек пустий
st.push(input[i]); // записуєм його в стек
else // в іншому випадку
{
if (GetPriority(st.top()) < GetPriority(input[i])) // якщо пріорітет символу > за пріорітет вершини стеку
st.push(input[i]); // додаєм оператор в стек
else // в іншому випадку
{
while ((!st.empty()) && (GetPriority(input[i]) <= GetPriority(st.top()))) // доки не знайдеться символ з меншим пріорітетом
{
output += st.top(); // додаєм вершину стеку в вихідний рядок
st.pop(); // видаляєм елемент зі стеку
}
st.push(input[i]); // записуєм оператор з вхідного рядка
}
}
}
else // в іншому випадку (якщо не оператор)
{
output += input[i]; // додаєм в вихідний рядок символ
}
}
while (!st.empty()) // доки стек не порожній
{
output += st.top(); // додаєм в вихідний рядок вершину
st.pop(); // вилучаєм елемент
}
return output; // повертаєм вихідний рядок
}
main.cpp
#include "infix_to_postfix.h"
#include <iostream>
using namespace std;
int main()
{
setlocale(0, "Ukr");
InfixToPostfix obj;
string str_inf, str_postf;
cout << "Enter infix