[教程][算法] Infix 转 Postfix

简介

Infix 表达式就是平常我们常用的,用来表达一个算术/方程式表达式的方式

比如说:

A + B * C - D

A + B * ( C + D * E)

( ( A + B ) * ( C - D ^ E) + F)

等等……

但是Infix(中缀表示法)对电脑来说太难处理了,所以就有了Postfix(或称Reversed Polish notation, RPN, 后缀表示法)

A + B * C - D

A + B * ( C + D * E)

( ( A + B ) * ( C - D ^ E) + F)

上述例子的Postfix 就是:

A B C * + D -

A B C D E * + * +

A B + C D E ^ - * F +

Postfix如何计算值

例子1:

在解释如何从Infix转Postfix之前,向来看看Postfix表达式如何求值:

A B C * + D -

看成:

1 2 3 * + 4 -

就是 1 + 2 * 3 - 4

现在有一个stack,专门储存operand

还有一个pointer,每次都向前移动一个字符(图片中被高亮起来的)

用图解释吧:

image

1 被入stack

image

2 被入栈

image

push 3

image

现在遇到一个operator

因为乘法需要两个operand,所以pop两个operator

然后进行运算,运算结果被push

image

加法,同理

image

push 4

image

pop 两个

进行运算 (顺序很重要!

然后push

image

接下来pointer抵达尾端,pop出

运算结果便是3

例子2:

A B + C D E ^ - * F +

看成这样吧:

1 2 + 3 4 5 ^ - * 6 +

( ( 1 + 2 ) * ( 3 - 4 ^ 5 ) + 6 )

image

image

image

image

image

image

image

image

image

image

image

Infix 转 Postfix

首先就是priority 列表:

  1. ( )

  2. * /

  3. + -

基本流程是这样的:

例子1:

A + B * C + D - E / F

1 + 2 * 3 + 4 - 5 / 5

image

image

image

image

image

image

image

image

image

image

image

image

image

image

例子2:

( ( A + B ) * ( C - D ^ E ) + F )

( ( 1 + 2 ) * ( 3 - 4 ^ 5 ) + 6 )

image

image

image

image

image

image

image

image

image

image

image

image

image

image

image

image

image

image

image

static string infixToPostfix(string exp)
{
	Dictionary<char, int> priority = new Dictionary<char, int>()
	{
		{'(',4},{')',4},{'^',3},{'*',2},{'/',2},{'+',1},{'-',1}
	};
	Stack<char> opt = new Stack<char>();
	string postfix = "";
	foreach (char c in exp)
	{
		if (priority.ContainsKey(c))
		{
			if (opt.Count == 0)
			{
				opt.Push(c);
			}
			else
			{
				if (c == ')')
				{
					while (opt.Count > 0 && opt.Peek() != '(')
					{
						postfix += opt.Pop();
					}
					opt.Pop();
				}
				else if (opt.Peek() == '(')
				{
					opt.Push(c);
				}
				else if (priority[c] > priority[opt.Peek()])
				{
					opt.Push(c);
				}
				else if (priority[c] < priority[opt.Peek()])
				{
					while (opt.Count > 0 && priority[c] <= priority[opt.Peek()] && opt.Peek()!='(')
					{
						postfix += opt.Pop();
					}
					opt.Push(c);
				}
				else if (priority[c] == priority[opt.Peek()])
				{
					postfix += opt.Pop();
					opt.Push(c);
				}
			}
		}
		else
		{
			postfix += c.ToString().Trim();
		}
	}
	while (opt.Count > 0)
	{
		postfix += opt.Pop();
	}
	return postfix;
}
« [教程][Minecraft] 以Tunggle 创建Minecraft Server [Tutorial] Setting Up Dropbox Files Sharing »
comments powered by Disqus