Загрузка данных


#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <string.h>
#include <stack>
#include <string>
using namespace std;

// Структура для узла дерева выражений
struct ExprNode {
    string value;
    ExprNode* left;
    ExprNode* right;
    
    ExprNode(string val) : value(val), left(NULL), right(NULL) {}
};

// Стек для узлов при построении дерева из постфиксной записи
struct NodeStack {
    ExprNode* node;
    NodeStack* next;
};

NodeStack* pushNode(NodeStack* top, ExprNode* node) {
    NodeStack* newTop = new NodeStack;
    newTop->node = node;
    newTop->next = top;
    return newTop;
}

NodeStack* popNode(NodeStack* top, ExprNode*& node) {
    if (!top) return NULL;
    node = top->node;
    NodeStack* temp = top;
    top = top->next;
    delete temp;
    return top;
}

// Разбиение строки на токены
int splitTokens(char* input, char tokens[][20]) {
    int count = 0;
    char* token = strtok(input, " ");
    while (token && count < 100) {
        strcpy(tokens[count++], token);
        token = strtok(NULL, " ");
    }
    return count;
}

// Построение дерева из постфиксной записи
ExprNode* buildTreeFromPostfix(char tokens[][20], int tokenCount) {
    NodeStack* stack = NULL;
    
    for (int i = 0; i < tokenCount; i++) {
        char* tok = tokens[i];
        
        // Проверка: оператор (+, -, *, /)
        if (strlen(tok) == 1 && (tok[0] == '+' || tok[0] == '-' || tok[0] == '*' || tok[0] == '/')) {
            ExprNode* node = new ExprNode(tok);
            stack = popNode(stack, node->right);  // правый операнд
            stack = popNode(stack, node->left);   // левый операнд
            stack = pushNode(stack, node);
        }
        else {  // Операнд (число или переменная)
            ExprNode* node = new ExprNode(tok);
            stack = pushNode(stack, node);
        }
    }
    
    ExprNode* root = NULL;
    stack = popNode(stack, root);
    return root;
}

// Префиксный обход (корень → левый → правый)
void prefixOrder(ExprNode* node, string& result) {
    if (!node) return;
    if (!result.empty()) result += " ";
    result += node->value;
    prefixOrder(node->left, result);
    prefixOrder(node->right, result);
}

// Постфиксный обход (левый → правый → корень)
void postfixOrder(ExprNode* node, string& result) {
    if (!node) return;
    postfixOrder(node->left, result);
    postfixOrder(node->right, result);
    if (!result.empty()) result += " ";
    result += node->value;
}

// Освобождение памяти
void deleteTree(ExprNode* node) {
    if (!node) return;
    deleteTree(node->left);
    deleteTree(node->right);
    delete node;
}

// Постфиксная → Префиксная
string postfixToPrefix(char* postfix) {
    // Копируем, так как strtok изменяет строку
    char buffer[200];
    strcpy(buffer, postfix);
    
    char tokens[100][20];
    int tokenCount = splitTokens(buffer, tokens);
    
    ExprNode* root = buildTreeFromPostfix(tokens, tokenCount);
    
    string prefix;
    prefixOrder(root, prefix);
    
    deleteTree(root);
    return prefix;
}

// Префиксная → Постфиксная (для проверки)
string prefixToPostfix(const string& prefix) {
    // Разбиваем префиксную строку на токены
    char buffer[200];
    strcpy(buffer, prefix.c_str());
    
    char tokens[100][20];
    int tokenCount = splitTokens(buffer, tokens);
    
    // Стек для поддеревьев (стек строк)
    stack<string> st;
    
    // Идём с конца к началу (для префиксной записи)
    for (int i = tokenCount - 1; i >= 0; i--) {
        char* tok = tokens[i];
        
        // Если оператор
        if (strlen(tok) == 1 && (tok[0] == '+' || tok[0] == '-' || tok[0] == '*' || tok[0] == '/')) {
            string left = st.top(); st.pop();
            string right = st.top(); st.pop();
            string expr = left + " " + right + " " + tok;
            st.push(expr);
        }
        else {  // Операнд
            st.push(tok);
        }
    }
    
    return st.top();
}

int main() {
    char postfix[200];
    
    cout << "========================================" << endl;
    cout << "Преобразование постфиксной записи в префиксную" << endl;
    cout << "========================================" << endl;
    cout << "Пример: 3 4 + 2 *" << endl;
    cout << endl;
    
    while (true) {
        cout << "Введите постфиксное выражение (или 'exit' для выхода): ";
        cin.getline(postfix, 200);
        
        if (strcmp(postfix, "exit") == 0) break;
        if (strlen(postfix) == 0) continue;
        
        // Постфиксная → Префиксная
        string prefix = postfixToPrefix(postfix);
        cout << "Префиксная запись: " << prefix << endl;
        
        // Проверка: Префиксная → Постфиксная
        string postfixBack = prefixToPostfix(prefix);
        cout << "Обратное преобразование (префиксная → постфиксная): " << postfixBack << endl;
        
        // Проверка совпадения
        if (strcmp(postfix, postfixBack.c_str()) == 0) {
            cout << "✓ ПРОВЕРКА ПРОЙДЕНА: исходная и полученная записи совпадают!" << endl;
        }
        else {
            cout << "✗ ПРОВЕРКА НЕ ПРОЙДЕНА!" << endl;
            cout << "Исходная:     " << postfix << endl;
            cout << "Полученная:   " << postfixBack << endl;
        }
        cout << endl;
    }
    
    return 0;
}