modify some mistakes.
This commit is contained in:
@@ -9,7 +9,7 @@
|
||||
|
||||
对于阶乘运算符,关键在于这是一个单目运算符,并且具有最高的优先级。由于它是一个单目运算符,因此在计算时只需要对操作数栈进行一次弹栈;而由于它具有最高的优先级,因此如果它在操作符栈中,则必然存在于栈顶,并且只能有一个阶乘运算符在栈中。需要注意的是,阶乘运算符的优先级与左括号是不可比较的,因为阶乘之后不可以跟一个左括号。
|
||||
|
||||
指数运算符的优先级仅次于阶乘,它的特殊性在于在通常约定的语意下,指数运算符是右结合的(其他诸如加法、乘法的运算符时左结合)。这就意味着`x^y^z`需要被理解为`x^(y^z)`而非`(x^y)^z`。为此,只需要对`prio`数组的这一项进行修改,使得`prio[POW][POW] = '<'`即可。
|
||||
指数运算符的优先级仅次于阶乘,它的特殊性在于在通常约定的语意下,指数运算符是右结合的(其他诸如加法、乘法运算符是左结合)。这就意味着`x^y^z`需要被理解为`x^(y^z)`而非`(x^y)^z`。为此,只需要对`prio`数组的这一项进行修改,使得`prio[POW][POW] = '<'`即可。
|
||||
|
||||
> 操作符栈的大小
|
||||
|
||||
@@ -36,15 +36,17 @@ bottom top
|
||||
+ 在进行实质的计算时,操作数栈不得为空。
|
||||
+ 输入表达式是否符合中缀表达式的规范。
|
||||
|
||||
对于第三个方面,检验的方法是,在任意操作符即将入栈时(即操作符之间的优先级比较以及可能的弹栈与计算操作已经结束),操作数栈的规模恰好比操作符栈大1。需要注意,上述结论中,不应该计入`\0`以及`'(`。
|
||||
对于第三个方面,检验的方法是,在任意操作符即将入栈时(即操作符之间的优先级比较以及可能的弹栈与计算操作已经结束),操作数栈的规模应该恰好比操作符栈大1。需要注意,上述结论中,不应该计入`\0`以及`(`。
|
||||
|
||||
对这个结论可以利用数学归纳法证明,主要就是对单目运算符和双目运算符进行讨论,这里不再赘述。
|
||||
|
||||
## 卡特兰数
|
||||
|
||||
括号匹配问题,栈混洗问题,异构二叉树的数量问题,都可以归入到卡特兰数,这里做一个简单的说明。
|
||||
括号匹配问题,栈混洗问题以及异构二叉树的数量问题,都可以归入到卡特兰数的范畴,这里做一个简单的说明。
|
||||
|
||||
异构二叉树的数量应该是这里最明确的问题,设`SP(n)`表示节点数量为`n`的二叉树的异构数量,以其中一个节点为为根,设左子树的规模为`k`,右子树的规模则为`n - k - 1`,因此有
|
||||
> 异构二叉树的数量
|
||||
|
||||
异构二叉树的数量应该是这里最明确的问题,设`SP(n)`表示节点数量为`n`的二叉树的异构数量,以其中一个节点为为根,设左子树的规模为`k`,则右子树的规模为`n - k - 1`,因此有
|
||||
|
||||
$$
|
||||
SP(n) = \Sigma_{k = 0}^{n - 1}SP(k)SP(n - k - 1)
|
||||
@@ -52,7 +54,9 @@ $$
|
||||
|
||||
其中,定义`SP(0) = 1`,这就是卡特兰数的递推公式。
|
||||
|
||||
对于括号匹配问题,设这里有`n`对括号,$S_n$为一个匹配的序列。我之前产生过一些错误的看法,比如可以把$S_n$分解为两个各自匹配的序列$S_k$和`S_{n - k}`,即
|
||||
> 括号匹配问题
|
||||
|
||||
对于括号匹配问题,设这里有`n`对括号,$S_n$为一个匹配的序列。我之前产生过一些错误的看法,比如可以把$S_n$分解为两个各自匹配的序列$S_k$和$S_{n - k}$,即
|
||||
|
||||
$$
|
||||
S_n = S_k S_{n - k}
|
||||
@@ -64,7 +68,7 @@ $$
|
||||
SP(n) = \Sigma_{k = 0}SP(k)SP(n - k)
|
||||
$$
|
||||
|
||||
答案当然是错误的,因为这里会产生重复计数的问题。比如设$S_3 = ()()()$,$S_1 = ()$,$S_2 = ()()$,那么$S_3 = S_1S_2 = S_2S_1$,会被计数两次。另一种划分$S_n = S_k()S_{n - k - 1)$也是同样的问题。
|
||||
答案当然是错误的,因为这里会产生重复计数的问题。比如设$S_3 = ()()()$,$S_1 = ()$,$S_2 = ()()$,那么$S_3 = S_1S_2 = S_2S_1$,会被计数两次。另一种划分$S_n = S_k()S_{n - k - 1}$也是同样的问题。
|
||||
|
||||
因此,这里正确的划分应该是$S_n = (S_k)S_{n - k}$,容易证明,此时没有上面的重复计数情况。此时就可以得到
|
||||
|
||||
@@ -72,12 +76,14 @@ $$
|
||||
SP(n) = \Sigma_{k = 0}^{n - 1}SP(k)SP(n - k - 1)
|
||||
$$
|
||||
|
||||
该结论和二叉树的问题一致。实际上,考虑二叉树的一次中序遍历,如果把每个节点的入栈视作一个左括号,出栈视作右括号,此时两个问题是完全等效的。此时$S_n = (S_k)S_{n - k}$中包围$S_K$的括号,就对应了二叉树的根节点。
|
||||
该结论和二叉树的问题一致。实际上,考虑二叉树的一次中序遍历,如果把每个节点的入栈视作一个左括号,出栈视作右括号,此时两个问题是完全等效的。此时$S_n = (S_k)S_{n - k}$中包围$S_K$的括号,就对应了二叉树中根节点的入栈与出栈操作。
|
||||
|
||||
> 栈混洗
|
||||
|
||||
对于栈混洗问题也可以得到相似的结论。考虑`n`个元素的栈混洗,设首元素在第`k`个位置出栈。显然,首元素出栈后栈为空。此时不难得到
|
||||
|
||||
```
|
||||
$$
|
||||
SP(n) = \Sigma_{k = 0}^{n - 1}SP(k)SP(n - k - 1)
|
||||
```
|
||||
$$
|
||||
|
||||
实际上,把栈混洗的入栈视作一个左括号,出栈视作一个右括号,则栈混洗问题与括号匹配问题完全一致,与二叉树异构也是完全一致的。此时,首元素的入栈和出栈分别对应了根节点的入栈和出栈。
|
||||
|
||||
Reference in New Issue
Block a user