255.0.0.0子网掩码相应的cidr前缀表示法是?_【洛谷日报#246】浅谈表达式的求值(Vol.2 进阶)...
Warning
在觀看本博客之前,請保證自己理解了表達式的三種表達方式。
本文旨在讓大家更深層次的了解表達式,基礎的知識就是上方的鏈接中所寫的。所以,在了解后綴表達式的運算原理之后,我將不會講述類似的前綴表達式的運算原理。
0 目錄
? 0 目錄 ? 1 淺談后綴表達式的還原 ? 2 前綴表達式介紹? I 簡單介紹? II 構造方法和還原方法? III 好玩的特性 ? 3 前中后綴表達式區別和聯系 ? 4 拓展 ? 5 總結1 淺談后綴表達式的還原
我們可以使用后綴表達式來構造表達式樹
我們想一下后綴表達式的計算
后序的時候,假設有一個排列如下: 數字1 數字2 計算符 那么這三個數可以被數字1[計算符]數字2代替(就是一次計算)我們再回頭看一看表達式樹的計算
f(左兒子)[now所代表的運算符]f(右兒子)所以,我們可以想到一種非常像后綴表達式計算的方法:
定義一種樹,支持將幾棵樹用另一個頂點作為根合并起來,就像這樣:
*+ - / / 1 2 3 4-------------* / + -/ / 1 2 3 4之后我們用一個棧S,利用以上性質計算:
inp -> 后綴表達式 struct Tree{...} stack<Tree> S for i from 1 to Nif(inp[i]是數字) 定義一個只有該數字的Tree,并加入到棧中else 創建一個只有這個字符的Tree,之后將棧頂的兩棵樹以它為根合并同時,我們也可以用字符串代替樹,那么樹的合并相當于字符串拼接,最后得到的是沒有括號的中綴表達式。
如果你想加括號的話,不妨利用以下文字,自己思考一下。
中序遍歷就是原式,但是我們通過運算優先級建樹,這時候受到括號的影響,計算的優先級會改變(括號里面的優先)。判斷的方式很簡單。
就比如除號,它在樹中左邊是加號,運算符優先級比它小,但是竟然先被計算,所以,加號所在子樹左右應該加上括號。
我們將模擬后綴表達式轉中綴表達式幫助你了解,用表達式樹的方法同理。
inp > 6 2 3 * + 4 / 5 - 掃到6 Stack > 6 掃到2 Stack > 6 2 掃到3 Stack > 6 2 3 掃到* "2" + "*" + "3" = "(2*3)" Stack > 6 (2*3) 掃到+ "6" + "+" + "(2*3)" = "(6+(2*3))" Stack > (6+(2*3)) 掃到4 Stack > (6+(2*3)) 4 掃到/ "(6+(2*3))" + "/" + "4" = "((6+(2*3))/4)" Stack > ((6+(2*3))/4) 掃到5 Stack > ((6+(2*3))/4) 5 掃到- ((6+(2*3))/4)" + "-" + "5" = "((((6+(2*3))/4)-5)" Stack > ((((6+(2*3))/4)-5)2 前綴表達式介紹
I 簡單介紹前綴表達式,類似于后綴表達式,是表達式的表達方式之一。
和后綴表達式相近,前綴表達式"將運算符寫在前面",從而可以加快運行速度(和后綴表達式一樣,在某種枚舉順序下,只使用出棧和入棧,加上基礎計算,就可以在$O(n)$的復雜度下運行出結果)。
打個比方,
前綴表達式舉例,中綴表達式為(6+2*3)/4-5中,前綴表達式就是
- / + 6 * 2 3 4 5II 構造方法和還原方法剛才講過,和后綴表達式一樣,前綴表達式也支持$O(n)$的計算和還原。區別如下
其他的和后綴表達式沒有區別。但是,由于從左到右判斷代碼明顯更好些(舉例:沒有人會選擇將已知字符串轉為數字的時候倒著處理,這樣還需要計算10的冪次),所以個人還是推薦使用后綴表達式處理方法。
......算了,還是給一下運算舉例吧。
- / + 6 * 2 3 4 5 掃到5,加入棧 +------------ | 5| | | | +------------ 掃到4,加入棧 +------------ | 5| 4| | | +------------ 掃到3,加入棧 +------------ | 5| 4| 3| | +------------ 掃到2,加入棧 +------------ | 5| 4| 3| 2| +------------ 掃到*,計算2*3,返回6,把6加入棧中 +------------ | 5| 4| 6| | +------------ 掃到6,加入棧 +------------ | 5| 4| 6| 6| +------------ 掃到+,計算6+6,返回12,把12加入棧中 +------------ | 5| 4|12| | +------------ 掃到/,計算12/4,返回3,把3加入棧中 +------------ | 5| 3| | | +------------ 掃到-,計算3-5,返回-2,把-2加入棧中 +------------ |-2| | | | +------------ 結束,返回-2III 好玩的特性我們不妨將前綴表達式的括號顯示,那么就會出現以下事情:
-(/(+(6,*(2,3))4),5)這就像一個個函數一樣了,也就是說,一個表達式
minus(divide(plus(6,multiply(2,3))4),5)可以只通過去括號和逗號就可以轉換為前綴表達式!
所以,That's it ! 我們就可以將一個只由函數和數字組合的表達式只通過拆括號和去逗號的方式轉為前綴表達式,在循環運算的時候甚至可以直接跳過這些省略的字符。
因此,我們就找到了一種全新的表達式計算方法:
對于每一個參數數量確定的函數,當參數為組合式的時候,遞歸處理前綴表達式;是數字的時候直接跳過。由此,我們就可以將一個表達式轉換為前綴表達式,從而解決問題。
為什么說數量確定?數量不確定的時候,函數的前綴表達式和其他的表達式一拼起來就會使得表達式出現歧義。
這種方法正好適用于這道題,感興趣的人可以去做一下。
3 前中后綴表達式區別和聯系
特性 | 中綴表達式 | 前綴表達式 | 后綴表達式 有無括號 | 有 | 無 | 無 運算方法 | 回溯 | 正向枚舉 | 反向枚舉 是否使用字符優先級 | 是 | 否 | 否 轉換(還原) | 單調棧 | 樹型數據結構 | 樹型數據結構 計算時間 | 一般O(n^2) | O(n) | O(n) 電腦解析難度 | 高 | 低 | 低 別名 | 中綴記法 | 波蘭表達式 | 逆波蘭表達式4 拓展
由于之前BB了這么多關于表達式的轉換,而且在中綴表達式去掉括號之后這三種表達式就是表達式樹的三種基礎遍歷方式,所以這里利用三種表達式表示法的互相轉換和還原解決知二推一的問題。由于死記硬背這些定理不好記住,所以建議和之前介紹的表達式求值和還原法理解。
前中推后:順序枚舉前綴表達式,獲取它在中綴表達式中的位置,從而將中綴表達式分成兩半,在左右分別繼續上面的操作,直到整棵表達式樹的形態確定。后中推前同理,只需倒著枚舉。
前后推中:順序枚舉前綴表達式,獲取它在后綴表達式中的位置,可以知道,后綴表達式中它的位置到它父親的位置就是它父親的右半子樹的后綴表達式,以此類推。
實際上,除了前傳開頭提到的中綴表達式計算方法,中綴表達式是存在
的計算方法的,在這里簡單一提。在這里,我們可以預先求出括號的匹配關系,之后,在一串表達式中,我們可以使用跳躍括號的方式找到本表達式中最后計算的那些符號(注意,這幾個符號的運算優先級應當一樣),將表達式劈成幾部分后分別計算這幾個表達式,就這樣遞歸下去。由于每一次我們都跳過了括號,所以運算復雜度是
的,但是常數隨優先級個數而變化(想一想,為什么)。當然,構造巴科斯范式并使用遞歸下降法可以讓速度達到一個新的高度,這些將會在之后講到。
5 總結
在消化了這篇文章以及它的前傳后,實際上簡單的表達式的求值和轉換都不是問題了。同時,你也可以將其使用在自創高級語言編譯器的解析過程當中,大大加快處理的速度。
最后,完結撒花!!!*★,°*:.☆( ̄▽ ̄)/$:*.°★* 。
創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎總結
以上是生活随笔為你收集整理的255.0.0.0子网掩码相应的cidr前缀表示法是?_【洛谷日报#246】浅谈表达式的求值(Vol.2 进阶)...的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: AIX中的进程管理
- 下一篇: access集团和abm_ACCESS集