數據結構Review——棧與隊列練習(中綴表達式轉後綴表達式以及後綴表達式計算)

題目來源:中國大學MOOC - 北京大學《數據結構與算法》- 第三章 棧與隊列 3.1 棧

中綴表達式與後綴表達式的定義在此不再贅述,僅舉例說明

序號 中綴表達式 後綴表達式 計算結果
1 23+(34*45)/(5+6+7) 23 34 45 * 5 6 + 7 + / + 108
2 1*(2-(3+4)) 1 2 3 4 + - * -5
3 1+2-3+4-5+6 1 2 + 3 - 4 + 5 - 6 + 5
4 a*(b-(c+d)) a b c d + - *

代碼如下:

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>

using namespace std;

/**最大正整數位數 */
const int MAX_BIT_LEN = 20;
/**字符串最大長度 */
const int MAX_STR_LEN = 200;
/**棧最大個數 */
const int MAX_STACK_SIZE = 200;
/**字符串轉數字 */
int string2num(const char *s);
/**數字轉字符串 */
char *num2string(char *s, int num);
/**刪除中綴表達式空格 */
bool removeSpace(char *infix);
/**中綴表達式轉後綴表達式 */
bool infix2postfix(char *infix, char *postfix);
/**計算後綴表達式 */
bool calPosfixExpression(char *postfix, int &result);

void solution();

struct Node
{
    char *item;
    struct Node *next;

    Node()
    {
        item = NULL;
        next = NULL;
    }
    Node(char *it)
    {
        item = it;
        next = NULL;
    }
};
typedef struct Node Node;

/**鏈式棧 */
class LinkedStack
{
private:
    Node *head;
    int maxSize;
    int size;

public:
    LinkedStack()
    {
        head = NULL;
        size = maxSize = 0;
    }
    LinkedStack(int m)
    {
        maxSize = m;
        size = 0;
        head = NULL;
    }

    bool pop(char *s)
    {
        if (size <= 0)
        {
            return false;
        }
        strcpy(s, head->item);
        Node *tmp = head->next;
        delete head;
        head = tmp;
        size--;
        return true;
    }

    bool top(char *s)
    {
        if (size <= 0)
        {
            return false;
        }
        strcpy(s, head->item);
        return s;
    }

    bool push(char *s)
    {
        if (size >= maxSize)
        {
            return false;
        }
        Node *node = new Node(s);
        node->next = head;
        head = node;
        size++;
        return true;
    }

    int getSize()
    {
        return size;
    }
};

int main()
{
    int T = 0;
    int t = 0;

    T = 1;
    while (t < T)
    {
        solution();
        t++;
    }

    system("pause");
    return 0;
}

void solution()
{
    // cout << string2num("1234") << endl;
    // char infix[MAX_STR_LEN] = "a*(b-(c+d)                )";
    // char infix[MAX_STR_LEN] = "1*(2-(3+4))";
    // char infix[MAX_STR_LEN] = "1+2-   3+4           -5+6";
    // char infix[MAX_STR_LEN] = "23+(34*45)/(5+6+7)";
    char infix[MAX_STR_LEN] = "\0";
    char postfix[MAX_STR_LEN] = "\0";
    cout << "input infix expression:" << endl;
    cin >> infix;
    cout << "origin infix expression:" << endl;
    cout << infix << endl;
    removeSpace(infix);
    cout << "after remove spaces:" << endl;
    cout << infix << endl;
    if (infix2postfix(infix, postfix))
    {
        cout << "the postfix exporession:" << endl;
        cout << postfix << endl;
        int res = 0;
        if (calPosfixExpression(postfix, res))
        {
            cout << "the result:" << endl;
            cout << res << endl;
        }
    }
}

/**字符串轉數字 */
int string2num(const char *s)
{
    int res = 0;
    int index = 1;
    for (int i = strlen(s) - 1; i >= 0; i--)
    {
        if (i == 0 && s[i] == '-')
        {
            res = res * (-1);
            break;
        }
        if (i == 0 && s[i] == '+')
        {
            break;
        }
        //出現非法字符則直接返回0
        if (s[i] < '0' || s[i] > '9')
        {
            return 0;
        }
        res += (s[i] - '0') * index;
        index *= 10;
    }
    return res;
}

/**數字轉字符串 */
char *num2string(char *s, int num)
{
    int org_num = num;
    int i = 0;
    if (num == 0)
    {
        s[0] = '0';
        s[1] = '\0';
        return s;
    }
    if (num < 0)
    {
        num = -1 * num;
    }
    //1234 得到 "4321"
    while (num != 0)
    {
        s[i++] = (num % 10) + '0';
        num /= 10;
    }
    //若num<0加上符號
    if (org_num < 0)
    {
        s[i++] = '-';
    }
    s[i] = '\0';
    //字符串逆置
    int len = strlen(s);
    for (int i = 0; i < len / 2; i++)
    {
        char tmp = s[i];
        s[i] = s[len - 1 - i];
        s[len - 1 - i] = tmp;
    }
    return s;
}

/**刪除中綴表達式中空格 */
bool removeSpace(char *infix)
{
    int i = 0;
    while (infix[i] != '\0')
    {
        if (infix[i] == ' ')
        {
            int j = i;
            for (; j < strlen(infix) - 1; j++)
            {
                infix[j] = infix[j + 1];
            }
            infix[j] = '\0';
            continue;
        }
        i++;
    }
    return true;
}

/**中綴表達式轉後綴表達式 */
bool infix2postfix(char *infix, char *postfix)
{
    LinkedStack *symbolStack = new LinkedStack(MAX_STACK_SIZE);
    int i = 0;
    int j = 0;
    char tmp[MAX_BIT_LEN] = "\0";
    while (infix[i] != '\0')
    {
        if (infix[i] == ' ')
        {
            i++;
            continue;
        }
        if (i == 0 && (infix[i] == '+' || infix[i] == '-' || infix[i] == '*' || infix[i] == '/'))
        {
            cout << "expression format error!" << endl;
            strcpy(postfix, "0");
            return false;
        }
        if (infix[i + 1] == '\0' && (infix[i] == '+' || infix[i] == '-' || infix[i] == '*' || infix[i] == '/'))
        {
            cout << "expression format error!" << endl;
            strcpy(postfix, "0");
            return false;
        }
        switch (infix[i])
        {
        case '0':
        case '1':
        case '2':
        case '3':
        case '4':
        case '5':
        case '6':
        case '7':
        case '8':
        case '9':
            postfix[j++] = infix[i];
            break;
        case '+':
            //
            //如果第一個字符即爲該符號記爲格式錯誤,如果當前字符的上一個字符也是+-*/記爲格式錯誤
            if (i == 0 || (i > 0 && (infix[i - 1] == '+' || infix[i - 1] == '-' || infix[i - 1] == '*' || infix[i - 1] == '/')))
            {
                cout << "expression format error!" << endl;
                strcpy(postfix, "0");
                return false;
            }
            while (symbolStack->top(tmp) && (tmp[0] != '('))
            {
                symbolStack->pop(tmp);
                postfix[j++] = ' ';
                postfix[j++] = tmp[0];
            }
            postfix[j++] = ' ';
            symbolStack->push("+");
            break;
        case '-':
            //如果第一個字符即爲該符號記爲格式錯誤,如果當前字符的上一個字符也是+-*/記爲格式錯誤
            if (i == 0 || (i > 0 && (infix[i - 1] == '+' || infix[i - 1] == '-' || infix[i - 1] == '*' || infix[i - 1] == '/')))
            {
                cout << "expression format error!" << endl;
                strcpy(postfix, "0");
                return false;
            }
            while (symbolStack->top(tmp) && (tmp[0] != '('))
            {
                symbolStack->pop(tmp);
                postfix[j++] = ' ';
                postfix[j++] = tmp[0];
            }
            postfix[j++] = ' ';
            symbolStack->push("-");
            break;
        case '*':
            //如果第一個字符即爲該符號記爲格式錯誤,如果當前字符的上一個字符也是+-*/記爲格式錯誤
            if (i == 0 || (i > 0 && (infix[i - 1] == '+' || infix[i - 1] == '-' || infix[i - 1] == '*' || infix[i - 1] == '/')))
            {
                cout << "expression format error!" << endl;
                strcpy(postfix, "0");
                return false;
            }
            while (symbolStack->top(tmp) && (tmp[0] == '*' || tmp[0] == '/'))
            {
                symbolStack->pop(tmp);
                postfix[j++] = ' ';
                postfix[j++] = tmp[0];
            }
            postfix[j++] = ' ';
            symbolStack->push("*");
            break;
        case '/':
            //如果第一個字符即爲該符號記爲格式錯誤,如果當前字符的上一個字符也是+-*/記爲格式錯誤
            if (i == 0 || (i > 0 && (infix[i - 1] == '+' || infix[i - 1] == '-' || infix[i - 1] == '*' || infix[i - 1] == '/')))
            {
                cout << "expression format error!" << endl;
                strcpy(postfix, "0");
                return false;
            }
            while (symbolStack->top(tmp) && (tmp[0] == '*' || tmp[0] == '/'))
            {
                symbolStack->pop(tmp);
                postfix[j++] = ' ';
                postfix[j++] = tmp[0];
            }
            postfix[j++] = ' ';
            symbolStack->push("/");
            break;
        case '(':
            symbolStack->push("(");
            break;
        case ')':
            while (symbolStack->top(tmp) && (tmp[0] != '('))
            {
                symbolStack->pop(tmp);
                postfix[j++] = ' ';
                postfix[j++] = tmp[0];
            }
            if (symbolStack->pop(tmp) == false)
            {
                cout << "expression format error!" << endl;
                strcpy(postfix, "0");
                return false;
            }
            break;
        default:
            if ((infix[i] <= 'Z' && infix[i] >= 'A') || (infix[i] <= 'z' && infix[i] >= 'a'))
            {
                postfix[j++] = infix[i];
            }
            else
            {
                cout << "illegal character" << endl;
                strcpy(postfix, "0");
                return false;
            }

            break;
        }
        i++;
    }
    while (symbolStack->top(tmp))
    {
        symbolStack->pop(tmp);
        postfix[j++] = ' ';
        if (tmp[0] == '(')
        {
            cout << "expression format error!" << endl;
            strcpy(postfix, "0");
            return false;
        }
        postfix[j++] = tmp[0];
    }
    return true;
}

/**
 * 計算後綴表達式
 * 例: 23 34 45 * 5 6 + 7 + / +
 * 結果:result = 108
 * 返回值: ture
 */
bool calPosfixExpression(char *postfix, int &result)
{
    LinkedStack *numberStack = new LinkedStack(MAX_STACK_SIZE);
    int i = 0;
    int j = 0;
    int res = 0;
    char nstr[MAX_BIT_LEN] = "\0";
    int tmp = 0;
    int num1 = 0, num2 = 0;
    char *s = NULL;

    //逐字符讀取後綴表達式
    while (postfix[i] != '\0')
    {
        //若非空格則持續讀取
        if (postfix[i] != ' ')
        {
            if (postfix[i] != '+' && postfix[i] != '-' && postfix[i] != '*' && postfix[i] != '/' && (postfix[i] < '0' || postfix[i] > '9'))
            {
                cout << "illegal character" << endl;
                result = 0;
                return false;
            }
            nstr[j++] = postfix[i];
            //最後一個字符後沒有空格,因此增加特例
            if (postfix[i + 1] != '\0')
            {
                i++;
                continue;
            }
        }

        nstr[j] = '\0';
        j = 0;

        if (strcmp(nstr, "+") == 0)
        {
            if (numberStack->getSize() < 2)
            {
                cout << "expression format error!" << endl;
                return false;
            }
            numberStack->pop(nstr);
            num2 = string2num(nstr);
            numberStack->pop(nstr);
            num1 = string2num(nstr);
            num2string(nstr, num1 + num2);
            s = (char *)malloc(sizeof(char) * strlen(nstr) + 1);
            strcpy(s, nstr);
            numberStack->push(s);
        }
        else if (strcmp(nstr, "-") == 0)
        {
            //除法應注意先出棧的是減數,後出棧的是被減數
            if (numberStack->getSize() < 2)
            {
                cout << "expression format error!" << endl;
                return false;
            }
            numberStack->pop(nstr);
            num2 = string2num(nstr);
            numberStack->pop(nstr);
            num1 = string2num(nstr);
            num2string(nstr, num1 - num2);
            s = (char *)malloc(sizeof(char) * strlen(nstr) + 1);
            strcpy(s, nstr);
            numberStack->push(s);
        }
        else if (strcmp(nstr, "*") == 0)
        {
            if (numberStack->getSize() < 2)
            {
                cout << "expression format error!" << endl;
                result = 0;
                return false;
            }
            numberStack->pop(nstr);
            num2 = string2num(nstr);
            numberStack->pop(nstr);
            num1 = string2num(nstr);
            num2string(nstr, num1 * num2);
            s = (char *)malloc(sizeof(char) * strlen(nstr) + 1);
            strcpy(s, nstr);
            numberStack->push(s);
        }
        else if (strcmp(nstr, "/") == 0)
        {
            //除法應注意先出棧的是除數,後出棧的是被除數,且除數不能爲0
            if (numberStack->getSize() < 2)
            {
                cout << "expression format error!" << endl;
                return false;
            }
            numberStack->pop(nstr);
            num2 = string2num(nstr);
            numberStack->pop(nstr);
            num1 = string2num(nstr);
            if (num2 == 0)
            {
                cout << "divid zero!" << endl;
                result = 0;
                return false;
            }
            num2string(nstr, num1 / num2);
            s = (char *)malloc(sizeof(char) * strlen(nstr) + 1);
            strcpy(s, nstr);
            numberStack->push(s);
        }
        else
        {
            s = (char *)malloc(sizeof(char) * strlen(nstr) + 1);
            strcpy(s, nstr);
            numberStack->push(s);
            strcpy(nstr, "\0");
        }

        i++;
    }
    //後綴表達式字符串讀取完成後,棧中應有且僅有1個元素
    if (numberStack->getSize() == 1 && numberStack->pop(nstr))
    {
        result = string2num(nstr);
        return true;
    }
    else
    {
        cout << "expression format error!" << endl;
        result = 0;
        return false;
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章