Java之Stack --- 棧

月盡天明發表於2012-12-09

前幾天,寫那個帶有算符優先順序的計算器的時候用到了,又查了一些資料,感覺棧還是很重要的。故而,再次總結一下。

棧是一種先進後出的資料集合。它通過五個操作對類Vector 進行了擴充套件 ,允許將向量視為堆疊。它提供了通常的pushpop 操作,以及取堆疊頂點的peek 方法、測試堆疊是否為空的 empty 方法、在堆疊中查詢項並確定到堆疊頂距離的search 方法。 

首次建立堆疊時,它不包含項。

它的構造方法是 public Stack()

一共有五個方法,這五個方法在你用到棧的時候基本都會用到,所以要掌握。

1. boolean   |   empty()  返回值是boolean值。 用於測試棧是否為空

2. E  |  peek()  返回值是你定義棧的時候的資料型別。 用於檢視棧頂部的物件,但是不從棧中移除。這個很重要,因為它不移除物件,只是檢視這個物件,而 pop() 這個方法會從棧中移除棧頂的物件。注意這兩個的區別!

3. E  |  pop()  用於移除堆疊頂部的物件,並返回該物件

4. E  |  push(E item)    將item壓入棧中,即壓入堆疊頂部。

5. int  |  search(Object o)  查詢某物件在堆疊中的位置。返回物件在堆疊中的位置,以1為基數。此方法返回距堆疊頂部最近的出現位置到堆疊頂部的距離;堆疊中最頂部項的距離為1。



下面說一下我的那個計算器吧!

目前一般的計算器進行計算時不能輸入括號,而且需要事先得到表示式的各項才能使用它,例如:若直接輸入:3+4*5,一般的計算器會在輸入乘號時,先得到7,輸入完成後的結果是35。

具有算符優先順序的計算器就是。按照數學中的符號優先順序 來計算。

這裡主要用到兩個棧,一個符號棧,一個數字棧

最主要的還是以一個演算法  ----  算符優先演算法


OperandType EvaluateExpression(){
	//算術表示式求值的算符優先演算法。設OPTR和OPND分別為運算子和運算數棧
	//OP為運算子集合
	InitStack(OPTR); Push(OPTR, '#');
	InitStack(OPND); c = getchar();
	while(c!= '#' || GetTop(OPTR)!='#'){
		if(!In(c, op)){
			Push(OPND, c);
			c = getchar();
		}else{
			while(Precede(GetTop(OPTR),c)){
				case '<'://棧頂元素優先權低
					Push(OPTR, C);
					c = getchar();
					break;
				case '='://脫括號並接受下一個字元
					pop(OPTR, x);
					c = getchar();
					break;
				case '>'://退棧並將運算結果入棧
					Pop(OPTR, theta);
					Pop(OPND, b);
					Pop(OPND, a);
					Push(OPND, Operate(a, theta, b));
					break;
			}
		}	
	}
	return GetTop(OPND);
}

Precede(GetTop(OPTR),c) 這個函式用來比較算符的優先順序

Operate(a, theta, b)  這個函式是用來計算結果

最後用GetTop(OPND)取出運算子棧的棧底,即結果存放的位置。。。


以下是我寫的具體實現:

//計算結果函式
	private static String Operate(String a, String theta, String b) {
		String result = "";
		double reusltDouble = 0.0;
		double aDouble = Double.parseDouble(a);
		double bDouble = Double.parseDouble(b);
		switch (theta) {
		case "+":
			reusltDouble = aDouble + bDouble;
			break;
		case "-":
			reusltDouble = aDouble - bDouble;
			break;
		case "*":
			reusltDouble = aDouble * bDouble;
			break;
		case "/":
			if (bDouble != 0.0) {
				reusltDouble = aDouble / bDouble;
			}
			else {
				System.out.println("被除數不能為0!");
				return null;
			}
			break;
		default:
			System.out.println("操作符輸入錯誤!");
			return null;
		}
		result = reusltDouble+"";
		return result;
		
	}


//判斷符號的優先順序
	private static String Precede(String ch1, String ch2) {
		String ch = "";
		if (ch1.equals("+")) {
			if (ch2.equals("+")) {
				ch = ">";
			}else if (ch2.equals("-")) {
				ch = ">";
			}else if (ch2.equals("*")) {
				ch = "<";
			}else if (ch2.equals("/")) {
				ch = "<";
			}else if (ch2.equals("(")) {
				ch = "<";
			}else if (ch2.equals(")")) {
				ch = ">";
			}else if (ch2.equals("#")) {
				ch = ">";
			}
		}else if (ch1.equals("-")) {
			if (ch2.equals("+")) {
				ch = ">";
			}else if (ch2.equals("-")) {
				ch = ">";
			}else if (ch2.equals("*")) {
				ch = "<";
			}else if (ch2.equals("/")) {
				ch = "<";
			}else if (ch2.equals("(")) {
				ch = "<";
			}else if (ch2.equals(")")) {
				ch = ">";
			}else if (ch2.equals("#")) {
				ch = ">";
			}
		}else if (ch1.equals("*")) {
			if (ch2.equals("+")) {
				ch = ">";
			}else if (ch2.equals("-")) {
				ch = ">";
			}else if (ch2.equals("*")) {
				ch = ">";
			}else if (ch2.equals("/")) {
				ch = ">";
			}else if (ch2.equals("(")) {
				ch = "<";
			}else if (ch2.equals(")")) {
				ch = ">";
			}else if (ch2.equals("#")) {
				ch = ">";
			}
		}else if (ch1.equals("/")) {
			if (ch2.equals("+")) {
				ch = ">";
			}else if (ch2.equals("-")) {
				ch = ">";
			}else if (ch2.equals("*")) {
				ch = ">";
			}else if (ch2.equals("/")) {
				ch = ">";
			}else if (ch2.equals("(")) {
				ch = "<";
			}else if (ch2.equals(")")) {
				ch = ">";
			}else if (ch2.equals("#")) {
				ch = ">";
			}
		}else if (ch1.equals("(")) {
			if (ch2.equals("+")) {
				ch = "<";
			}else if (ch2.equals("-")) {
				ch = "<";
			}else if (ch2.equals("*")) {
				ch = "<";
			}else if (ch2.equals("/")) {
				ch = "<";
			}else if (ch2.equals("(")) {
				ch = "<";
			}else if (ch2.equals(")")) {
				ch = "=";
			}
		}else if (ch1.equals(")")) {
			if (ch2.equals("+")) {
				ch = ">";
			}else if (ch2.equals("-")) {
				ch = ">";
			}else if (ch2.equals("*")) {
				ch = ">";
			}else if (ch2.equals("/")) {
				ch = ">";
			}else if (ch2.equals("(")) {//此時會報錯!
				System.out.println("語法錯誤!()");
				ch = " ";
			}else if (ch2.equals(")")) {
				ch = ">";
			}else if (ch2.equals("#")) {
				ch = ">";
			}
		}else if (ch1.equals("#")) {
			System.out.println(ch2);
			if (ch2.equals("+")) {
				ch = "<";
			}else if (ch2.equals("-")) {
				ch = "<";
			}else if (ch2.equals("*")) {
				ch = "<";
			}else if (ch2.equals("/")) {
				ch = "<";
			}else if (ch2.equals("(")) {//此時會報錯!
				ch = "<";
			}else if (ch2.equals(")")) {
				ch = " ";
				System.out.println("語法錯誤!#)");
			}else if (ch2.equals("#")) {
				ch = "=";
			}
		}
		
		return ch;
	}

// 計算器
	public static double EvaluateExpression() {
		double result = 0.0;
		Stack<String> OPTR = new Stack<String>();
		Stack<String> OPND = new Stack<String>();
		OPTR.push("#");
		int i = 0;
		String c = "";
		c = tolArray[i];
		while (!c.equals("#") || !OPTR.peek().equals("#")) {
			System.out.println(OPTR.peek());
			if (!exitInOtherArray(c)) {
				System.out.println(c);
				OPND.push(c);
				i++;
				c = tolArray[i];
			} else {
				System.out.println(OPTR.peek());
				System.out.println(c);
				switch (Precede(OPTR.peek(), c)) {
				case  "<":
					OPTR.push(c);
					i++;
					c = tolArray[i];
					break;
				case "=":
					OPTR.pop();
					i++;
					c = tolArray[i];
					break;
				case ">":
					String theta = OPTR.pop();
					String b = OPND.pop();
					String a = OPND.pop();
					OPND.push(Operate(a, theta, b));
					break;

				default:
					break;
				}
			}

		}
		result = Double.parseDouble(OPND.peek());
		return result;
	}



相關文章