資料結構之棧及Java實現
阿新 • • 發佈:2019-01-30
一、棧的基本介紹
棧是一種只允許在一端進行插入或刪除的線性表,也就是說先進後出。棧的操作端通常被稱為棧頂,另一端被稱為棧底,棧的插入操作稱為壓棧(push),棧刪除操作稱為出棧(pop)。壓棧是把新元素放到棧頂元素的上面,使之成為新的棧頂元素;出棧則是把棧頂元素刪除掉,使其相鄰的元素成為新的棧頂元素。
二、棧的Java實現
棧的實現方式主要分為兩種,一種是基於陣列實現的,另一種則是基於連結串列。順序儲存的棧稱為順序棧;鏈式儲存的棧稱為鏈式棧。不管是基於何種形式,一般都要實現幾個方法,分別為檢查棧是否為空,是否已滿,壓棧操作和出棧操作,值得說明的是,在鏈式棧中無需檢測棧是否已滿,只要記憶體足夠大,原理上鍊式棧是不會滿的。下面分別介紹兩種方式的實現:
- 基於陣列的順序棧
public class ArrayStack<T> {
private T data[];
private int maxSize;
private int top;
//初始化棧
public ArrayStack(int maxSize){
this.maxSize = maxSize;
data = (T[]) new Object[maxSize];
this.top = -1;
}
//判斷棧是否已空
public boolean isNull (){
if(top == -1){
return true;
}
return false;
}
//判斷棧是否已滿
public boolean isFull(){
if(top == maxSize-1){
return true;
}
return false;
}
//將value壓棧
public boolean push(T value){
if(isFull()){
return false;
}
top++;
data[top] = value;
return true;
}
//取出棧頂元素
public T pop(){
if(isNull()){
return null;
}
T tmp = data[top];
data[top] = null;
top--;
return tmp;
}
public static void main(String args[]){
ArrayStack<String> as = new ArrayStack<String>(4);
as.push("sasa");
as.push("qwwq");
as.push("erer");
as.push("ddsd");
//測試棧已滿時的情況
System.out.println(as.push("hhhhh"));
//測試出棧順序
System.out.println(as.pop());
System.out.println(as.pop());
System.out.println(as.pop());
System.out.println(as.pop());
}
}
測試結果:
false
ddsd
erer
qwwq
sasa
- 基於連結串列的鏈式棧
public class NodeStack<T> {
private Node<T> top = null;
public NodeStack(){
this.top = null;
}
//判斷棧是否為空
public boolean isNull(){
if(top == null){
return true;
}
return false;
}
//壓棧
public boolean push(T data){
Node<T> node = new Node<T>(data);
node.setNext(top);
top = node;
return true;
}
//出棧
public T pop(){
if(isNull()){
return null;
}
T tmp = top.data;
top = top.getNext();
return tmp;
}
//取出棧頂的值
public T peek(){
if(isNull()){
return null;
}
return top.data;
}
class Node<T>{
private T data;
private Node<T> next;
public Node(T value){
this.data = value;
}
public Node<T> getNext(){
return this.next;
}
public void setNext(Node<T> n){
this.next = n;
}
public T getData(){
return this.data;
}
public void setData(T d){
this.data = d;
}
}
public static void main(String args[]){
NodeStack<String> ns = new NodeStack<String>();
//測試是否為空
System.out.println(ns.isNull());
//壓棧測試
ns.push("asdwqewqewqea");
ns.push("ewewwqsdsadsd");
ns.push("ffddsfsdfdfdf");
//測試是否為空
System.out.println(ns.isNull());
//出棧測試
System.out.println(ns.pop());
System.out.println(ns.pop());
System.out.println(ns.pop());
//測試是否為空
System.out.println(ns.isNull());
}
}
測試結果:
true
false
ffddsfsdfdfdf
ewewwqsdsadsd
asdwqewqewqea
true
三、棧相關演算法實現
括號匹配問題是棧的一個經典應用示例,輸入表示式即一個字串,判斷這個字串的括號是不是匹配。
思路如下所示:
1.迴圈遍歷字串,讀取字元每一個字元
1.1如果是左括號,則入棧;
1.2如果ch是右括號,則需要進一步判斷:
如果棧空:
說明多出右括號,直接返回false;
如果棧不空,ch和棧頂比較:
如果不同,返回false;
如果匹配,則出棧一次;
2.迴圈結束後棧空,說明左括號匹配完了,則返回true,迴圈結束後棧不空,則返回false。
實現程式碼
public class StrMatch {
public boolean match(String str){
NodeStack<Character> strMatch = new NodeStack<Character>();
char tmp;
//迴圈遍歷字串
for(int i=0;i<str.length();i++){
tmp = str.charAt(i);
//判斷是否為左括號
if(isLeft(tmp)){
//左括號入棧
strMatch.push(tmp);
}
//判斷是否為右括號
else if(isRight(tmp)){
//如果棧已空,則右括號不能匹配,返回false
if(strMatch.isNull()){
return false;
}
//如果右括號與棧頂的左括號相匹配,移除棧頂的左括號
if(corespd(strMatch.peek(),tmp)){
strMatch.pop();
}
}
}
//迴圈遍歷結束,如果棧已空,則說明匹配完畢,返回true
if(strMatch.isNull()){
return true;
}
//否則,返回false
return false;
}
//判斷左右括號是否對應
public boolean corespd(char a,char b){
if(a == '('&&b ==')')
return true;
if(a == '['&&b==']')
return true;
if(a == '{'&&b == '}')
return true;
return false;
}
//判斷是否為左括號
public boolean isLeft(char c){
if(c == '(' || c == '[' ||c == '{'){
return true;
}
return false;
}
//判斷是否為右括號
public boolean isRight(char c){
if(c == ')' || c==']' || c=='}'){
return true;
}
return false;
}
public static void main(String[] args) {
// 測試字串
StrMatch sm = new StrMatch();
String inputStr1 = "{[(2+4)+(3-5)/9]*4+1}*{[(2-4)+(3-5)*9]*(4+1)}";
String inputStr2 = "{[(2+4)+(3-5)/9]*4+1}*{[(2-4)+(3-5)*9]*(4+1}";
String inputStr3 = "{[(2+4)+(3-5)/9]*4+1}*[(2-4)+(3-5)*9]*(4+1)}";
System.out.println(sm.match(inputStr1));
System.out.println(sm.match(inputStr2));
System.out.println(sm.match(inputStr3));
}
}
輸出結果
true
false
false