数据结构——逆波兰式
生活随笔
收集整理的這篇文章主要介紹了
数据结构——逆波兰式
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
很久沒有關注算法和數據結構,大部分知識都已經忘記了;是時間好好回爐一下了,說實話干讀數據機構這本書還是挺枯燥而且這本書原理性比較多,有一定的難度。這不剛看到逆波蘭式廢了好大勁才搞懂,老了。。。
逆波蘭式
逆波蘭式(Reverse Polish notation,RPN,或逆波蘭記法),也叫后綴表達式(將運算符寫在操作數之后)
一個表達式E的后綴形式可以如下定義: (1)如果E是一個變量或常量,則E的后綴式是E本身。 (2)如果E是E1 op E2形式的表達式,這里op是如何二元操作符,則E的后綴式為E1'E2' op,這里E1'和E2'分別為E1和E2的后綴式。 (3)如果E是(E1)形式的表達式,則E1的后綴式就是E的后綴式。 如:我們平時寫a+b,這是中綴表達式,寫成后綴表達式就是:ab+ (a+b)*c-(a+b)/e的后綴表達式為: (a+b)*c-(a+b)/e →((a+b)*c)((a+b)/e)- →((a+b)c*)((a+b)e/)- →(ab+c*)(ab+e/)- →ab+c*ab+e/-算法實現
將一個普通的中序表達式轉換為逆波蘭表達式的一般算法是: 首先需要分配2個棧,一個作為臨時存儲運算符的棧S1(含一個結束符號),一個作為輸入逆波蘭式的棧S2(空棧),S1??上确湃雰炏燃壸畹偷倪\算符#,注意,中綴式應以此最低優先級的運算符結束??芍付ㄆ渌址?#xff0c;不一定非#不可。從中綴式的左端開始取字符,逐序進行如下步驟: (1)若取出的字符是操作數,則分析出完整的運算數,該操作數直接送入S2棧 (2)若取出的字符是運算符,則將該運算符與S1棧棧頂元素比較,如果該運算符優先級(不包括括號運算符)大于S1棧棧頂運算符優先級,則將該運算符進S1棧,否則,將S1棧的棧頂運算符彈出,送入S2棧中,直至S1棧棧頂運算符低于(不包括等于)該運算符優先級,最后將該運算符送入S1棧。 (3)若取出的字符是“(”,則直接送入S1棧頂。 (4)若取出的字符是“)”,則將距離S1棧棧頂最近的“(”之間的運算符,逐個出棧,依次送入S2棧,此時拋棄“(”。 (5)重復上面的1~4步,直至處理完所有的輸入字符 (6)若取出的字符是“#”,則將S1棧內所有運算符(不包括“#”),逐個出棧,依次送入S2棧。 完成以上步驟,S2棧便為逆波蘭式輸出結果。不過S2應做一下逆序處理。便可以按照逆波蘭式的計算方法計算了!代碼程序
//'1 + 2 * 3 + (4 * 5 + 6) * 7'function ReversePolish() {this.operatorStack = [];// this.operator = ['+', '-', '*', '/', '(', ')'];this.operator = {'+': 1,'-': 1,'*': 2,'/': 2,'(': 10,')': 10};this.rp = []; }ReversePolish.prototype.convert = function(str) {debugger;// ('15 + 2 * 3 + (4 * 5 + 6) * 7').trim().replace(/\s+/g, '').split(/([\+|\-|\*|\/|\(|\)])/)// ["15", "+", "2", "*", "3", "+", "", "(", "4", "*", "5", "+", "6", ")", "", "*", "7"] str.trim().replace(/\s+/g, '').split(/([\+|\-|\*|\/|\(|\)])/).filter(e => !!e).forEach(e => {if (/[0-9]/g.test(e)) { // 數字直接放入逆波蘭式數組this.rp.push(e);} else {if (this.operatorStack.length === 0) {// 操作符棧為空直接壓入棧this.operatorStack.push(e);} else {if (e === '(') { // 左括號直接入棧this.operatorStack.push(e);} else if (e === ')') { // 右括號彈出所有的操作符進入逆波蘭數組,直至遇到 (, (不進入逆波蘭數組let op = this.operatorStack.pop();while(op !== '(') {this.rp.push(op);op = this.operatorStack.pop();}// this.operatorStack.pop();} else { // 遇到其他操作符則彈出所有棧頂元素,直至遇到優先級更低的操作符,但是不處理(let op = this.operatorStack.pop();while(op && this.operator[op] >= this.operator[e] && op !== '(') {this.rp.push(op);op = this.operatorStack.pop();}if (op) {this.operatorStack.push(op);}this.operatorStack.push(e);}}}});// 運行結束后將所有的操作符棧彈出let op = this.operatorStack.pop();while(op) {this.rp.push(op);op = this.operatorStack.pop();}console.log(this.rp.join(' ')); };//15 2 3 * + 4 5 * 6 + 7 * + ReversePolish.prototype.eval = function(){let numberStack = [];this.rp.forEach(e => {if (/[0-9]/g.test(e)) {numberStack.push(Number(e));} else if (this.operator[e]) {let n2 = numberStack.pop();let n1 = numberStack.pop();switch(e) {case '+':numberStack.push(n1 + n2);break;case '-':numberStack.push(n1 - n2);break;case '*':numberStack.push(n1 * n2);break;case '/':numberStack.push(n1 / n2);}}});return numberStack.pop(); }let rp = new ReversePolish(); rp.convert('15 + 2 * 3 + (4 * 5 + 6) * 7'); rp.eval();感覺逆波蘭式不僅是一種方法,更是一種思想,逆波蘭式這種計算方法沒有必要知道任何運算符優先規則。就像我們實際業務中有很多邏輯判斷、各種優先級的場景,是否也可以使用逆波蘭式的思想來解決?上面的例子也是比較簡單的情況,沒有考慮運算符的執行順序,對于2^2^3這個種,實際是等于2^8等于256,而不是4^3=64.
?
轉載于:https://www.cnblogs.com/dojo-lzz/p/9000223.html
總結
以上是生活随笔為你收集整理的数据结构——逆波兰式的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: bzoj 1753: [Usaco200
- 下一篇: popoverController(iP