数据结构之栈(四)

来源:互联网 发布:单反推荐 知乎 编辑:程序博客网 时间:2024/06/05 18:03

        本文将继续扩展Stack在Arithmetical Expression的处理方面的应用,其中包括:“Postfix2Prefix”、“Postfix2Infix”和“Infix2Postfix”。


一、Postfix2Prefix

        它是通过多次入栈和出栈来完成的。主要步骤是:遍历“postfix string”:

        1)是算子先压栈;

        2)是算符就先取出它需要的算子,调整顺序(保证算符在前,算子在后),并焊接在一个整体(string),再压栈。

bool IsOperator(char c){    if (c == '+' || c == '-' || c == '*' || c == '/' || c == '^')        return true;    else        return false;}void Postfix2Prefix(string & postfix, string & prefix){    // convert the input postfix expression to prefix format    StackAsLinkedList stack;    for (unsigned int i = 0; i < postfix.length(); ++i)    //process each char in the postfix string from left to right    {        string s{ postfix[i] };        if (std::isdigit(postfix[i]))            stack.Push(*new String(s));        else if (IsOperator(postfix[i]))        {            String & arg2 = dynamic_cast<String&>(stack.Pop());            String & arg1 = dynamic_cast<String&>(stack.Pop());            stack.Push(*new String(s + string(arg1) + string(arg2)));            delete &arg1;            delete &arg2;        }    }    String & arg = dynamic_cast<String&>(stack.Pop());    prefix = string(arg);    delete & arg;}

二、Postfix2Infix

        它的原理于上面的相似,只是在调整顺序的时候,保证“算符在算子中间,并添加圆括号”。

void Postfix2Infix(string & postfix, string & infix){    // convert the input postfix expression to infix format    StackAsLinkedList stack;    for (unsigned int i = 0; i < postfix.length(); ++i)    //process each char in the postfix string from left to right    {        string s{ postfix[i] };        if (std::isdigit(postfix[i]))            stack.Push(*new String(s));        else if (IsOperator(postfix[i]))        {            String & arg2 = dynamic_cast<String&>(stack.Pop());            String & arg1 = dynamic_cast<String&>(stack.Pop());            stack.Push(*new String(string("(") + string(arg1) + s + string(arg2) + string(")")));            delete &arg1;            delete &arg2;        }    }    String & arg = dynamic_cast<String&>(stack.Pop());    infix = string(arg);    delete & arg;}

注:类似的原理,也可以处理“prefix expression”。


三、Infix2Postfix

        它的原理要稍微复杂一些。需要比较运算符的优先级和考虑运算符的结合性以及圆括号。它也是遍历“infix string”:

        1)遇到数字,直接append到“postfix string”;

        2)遇到算符,与栈顶的算符比较优先级,如果栈顶算符优先级高,则将栈顶算符append到“postfix string”,反复进行比较,知道遇到圆括号,或者栈顶算符优先级更低为止,最后将新算符压栈(这样,栈内的算符优先级是从低到高顺序排序);

        3)遇到左括号压栈,遇到右括号出栈。(对于括号是成对处理)

int GetOperatorWeight(char op){    int weight = -1;    switch (op)    {    case '+':    case '-':        weight = 1;        break;    case '*':    case '/':        weight = 2;        break;    case '^':        weight = 3;        break;    }    return weight;}bool IsRightAssociative(char op){    if (op == '^')        return true;    else        return false;}bool HasHigherPrecendence(char lOperator, char rOperator){    int op1Weight = GetOperatorWeight(lOperator);    int op2Weight = GetOperatorWeight(rOperator);    // If operators have equal precedence, return true if they are left associative.     // return false, if right associative.     // if operator is left-associative, left one should be given priority.     if (op1Weight == op2Weight)    {        if (IsRightAssociative(lOperator))            return false;        else            return true;    }    return op1Weight > op2Weight ? true : false;}void Infix2Postfix(string & infix, string & postfix){    // convert the input infix expression to postfix format    StackAsLinkedList stack;    for (unsigned int i = 0; i < infix.length(); ++i)    //process each char in the postfix string from left to right    {        string s{ infix[i] };        if (infix[i] == ' ' || infix[i] == ',')    // If character is a delimitter, move on.             continue;        else if (std::isdigit(infix[i]))            postfix += infix[i];        else if (IsOperator(infix[i]))    // If character is operator        {            while (!stack.IsEmpty() &&                string(dynamic_cast<String&>(stack.Top())) != string("(") &&                HasHigherPrecendence(string(dynamic_cast<String&>(stack.Top()))[0], infix[i]))    // operators in stack ordered by precedence            {                String & arg = dynamic_cast<String&>(stack.Pop());                postfix += string(arg);                delete &arg;            }            stack.Push(*new String(string{ infix[i] }));        }        else if (infix[i] == '(')        {            stack.Push(*new String(string{ infix[i] }));        }        else if (infix[i] == ')')    // a pair of parenthesis is a processing unit        {            while (string(dynamic_cast<String&>(stack.Top())) != string("("))            {                String & arg = dynamic_cast<String&>(stack.Pop());                postfix += string(arg);                delete &arg;            }            stack.Pop();        }    }    while (!stack.IsEmpty())    {        String & arg = dynamic_cast<String&>(stack.Pop());        postfix += string(arg);        delete &arg;    }}

注:从该函数对圆括号的成对处理方法,可以扩展:在处理C++代码时,由于代码块是用花括号包裹,而花括号也是成对出现的,也可以采用栈进行缓存处理。或者,更简单的办法是“计算”。设定“int count = 0”;遇到左花括号则“++count”;遇到右花括号则“--count”;


0 0
原创粉丝点击