繁体   English   中英

在三元字符串中处理一元非运算符的调车码算法

[英]Shunting yard algorithm with handling unary NOT operator in Ternary string

我目前正在编写三元逻辑字符串的中缀到前缀传输。 具体来说,字符串中只有三个操作数 T、F、U 和三个运算符 AND、NOT、OR 和括号。 Not 的优先级高于 AND,OR 和 AND OR 具有相同的优先级。 这是我从原始调车场算法更改的代码,但某些输入的翻译不正确

string Infix_To_Prefix(string expression){
    string prefix_expression = "";
    stack<char> char_stack;
    unordered_map<char,int> Precendence;
    Precendence['~'] = 2;
    Precendence['|'] = 1;
    Precendence['&'] = 1;

    for(int i=0;i<expression.size();i++)
    {
        char token = expression[i];
        if(isOperator(token))
        {
            while(!char_stack.empty() and isOperator(char_stack.top()))
            {
                if(Precendence[token] < Precendence[char_stack.top()])
                {
                    prefix_expression+=char_stack.top();
                    char_stack.pop();
                    continue;
                }
                break;
            }
            char_stack.push(token);
        }

        else if(token == '(')
        {
            char_stack.push(token);
        }
        else if(token == ')')
        {
            while(!char_stack.empty() and char_stack.top() != '(')
            {
                prefix_expression+=char_stack.top();
                char_stack.pop();
            }
            char_stack.pop();
        }
        else if(isOperand(token))
        {
            prefix_expression+=token;
        }

    }
    while(!char_stack.empty())
    {
        prefix_expression+=char_stack.top();;
        char_stack.pop();
    }
    return prefix_expression;
}

在您的代码中,您检查优先级:

if(Precendence[token] < Precendence[char_stack.top()])
{
    prefix_expression+=char_stack.top();
    char_stack.pop();
    continue;
}

在你在评论中引用的程序中,肯定不是原来的调车场实现,代码是

if ((isAssociative(token, LEFT_ASSOC) && 
        cmpPrecedence(token, stack.peek()) <= 0) || 
    (isAssociative(token, RIGHT_ASSOC) && 
        cmpPrecedence(token, stack.peek()) < 0)) 
{
    out.add(stack.pop());   
    continue;
}

因此,您的测试与提供的代码在右关联运算符的情况下所做的相同,这就是您的代码所做的。 如果您希望您的运算符是左关联的,您需要将<更改为<= ,就像您正在改编的代码中一样。

但是,这对于一元运算符不起作用,因为一元运算符需要是右结合的,至少在调车场算法的实现中通常显示的简单视图中是这样。

更准确地说,一元运算符应该始终被压入堆栈,而不管其前面的运算符的优先级如何; 由于它不使用右手运算符,因此它不与前一个运算符竞争,只与后一个运算符竞争。 因此,作为传入标记的一元运算符必须比堆栈上的任何运算符具有更高的优先级,尽管堆栈上的一元运算符可能具有也可能不具有比传入运算符标记更高的优先级。 如果一元运算符是最高优先级运算符,则使其右结合将产生这种效果。 所以我认为特殊情况的一元运算符更干净,就像你已经用括号做的那样:

for (char token: expression)  {
  if (token == '(' || token == '~')
    char_stack.push(token);
  else if (isOperator(token)) {
    while (!char_stack.empty()
           and isOperator(char_stack.top())
           and Precendence[token] < Precendence[char_stack.top()]) {
        prefix_expression+=char_stack.top();
        char_stack.pop();
    }
    char_stack.push(token);
  }
  else if(token == ')') {
    while(!char_stack.empty() and char_stack.top() != '(') {
      prefix_expression+=char_stack.top();
      char_stack.pop();
    }
    char_stack.pop();
  }
  else if(isOperand(token))
    prefix_expression+=token;
}

弹出堆栈的各种循环之间的相似性应该建议简化,这通常在运算符优先级解析器中实现(Shunting Yard 就是一个例子)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM