从数据结构的角度看,栈是一种特殊的线性表,即,栈是限定仅在表尾进行插入或删除操作的线性表。栈的表尾端称为栈顶,表头端称为栈底。不含元素的空表称为空栈。
假设栈
S=(a1,a2,...,an)
,则称
an
为栈顶元素,栈的修改是按后进先出的原则进行的,即先进栈的后出栈,后进栈的先出栈。栈的示意图如下:
栈的抽象数据类型的定义如下:
下面则为栈的Java实现代码:
/**
* 顺序栈接口
*/
public interface Stack<T> {
/**
* 构造一个空栈
*/
void InitStack(int initsize);
/**
* 销毁栈
*/
void DestroyStack();
/**
* 将栈置为空栈
*/
void ClearStack();
/**
* 判断栈是否为空,若为空,则返回TRUE,否则,返回False
* @return
*/
Boolean StackEmpty();
/**
* 返回栈的元素个数
* @return
*/
int StackLength();
/**
* 若栈不空,则返回栈的栈顶元素
*/
T GetTop();
/**
* 插入元素e为新的栈顶元素
* @param e
*/
void Push(T e);
/**
* 若栈不空,则删除栈的栈顶元素,并返回栈顶元素
* @return
*/
T Pop();
/**
* 从栈底到栈顶依次对栈中每个元素调用函数visit()。
*/
void StackTraverse();
/**
* visit函数
* @param e
*/
T visit(T e);
}
/**
* 顺序栈接口的实现类
*/
public class StackImpl<T> implements Stack<T>{
/**
* 栈对象
*/
private Object[] stack;
/**
* 栈元素的最大个数
*/
private int maxsize;
/**
* 栈顶元素索引
*/
private int top;
/**
* 构造一个空栈
*/
public void InitStack(int initsize){
this.maxsize = initsize;
this.stack = new Object[initsize];
this.top = -1;
}
/**
* 销毁栈
*/
public void DestroyStack(){
if(this.stack != null){//如果栈存在
this.stack = null;
this.top = -1;
this.maxsize = 0;
}else{
throw new IllegalArgumentException("栈不存在");
}
}
/**
* 将栈置为空栈
*/
public void ClearStack(){
if(this.stack != null){//如果栈存在
this.stack = new Object[this.maxsize];
this.top = -1;
}else{
throw new IllegalArgumentException("栈不存在");
}
}
/**
* 判断栈是否为空,若为空,则返回TRUE,否则,返回False
* @return
*/
public Boolean StackEmpty(){
if(this.stack != null){//如果栈存在
return this.top == -1 ? true : false;
}else{
throw new IllegalArgumentException("栈不存在");
}
}
/**
* 返回栈的元素个数
* @return
*/
public int StackLength(){
if(this.stack != null){//如果栈存在
return this.top + 1;
}else{
throw new IllegalArgumentException("栈不存在");
}
}
/**
* 若栈不空,则返回栈的栈顶元素
*/
public T GetTop(){
if(this.stack != null && this.top != -1){//如果栈存在且不为空
return (T) this.stack[top];
}else{
throw new IllegalArgumentException("栈不存在或者为空");
}
}
/**
* 插入元素e为新的栈顶元素
* @param e
*/
public void Push(T e){
if(this.stack != null && this.top < maxsize - 1){//如果栈存在且栈没有满
this.stack[++top] = e;
}else{
throw new IllegalArgumentException("栈不存在或者栈已满");
}
}
/**
* 若栈不空,则删除栈的栈顶元素,并返回栈顶元素
* @return
*/
public T Pop(){
if(this.stack != null && this.top != -1){//如果栈存在且不为空
Object[] newStack = new Object[this.maxsize];
T e;
for(int i = 0;i < this.top;i++)
newStack[i] = this.stack[i];
e = (T) this.stack[this.top];
this.stack = newStack;
this.maxsize--;
this.top--;
return e;
}else{
throw new IllegalArgumentException("栈不存在或者为空");
}
}
/**
* 从栈底到栈顶依次对栈中每个元素调用函数visit()
*/
public void StackTraverse(){
Object[] newStack = new Object[this.maxsize];
for(int i = 0;i <= this.top;i++)
newStack[i] = visit((T) this.stack[i]);
this.stack = newStack;
}
/**
* visit函数
* @param e
*/
public T visit(T e){
return (T) e.toString();
}
/**
* 主函数
* @param args
*/
public static void main(String[] args) {
Stack stack = new StackImpl();
stack.InitStack(4);//初始化栈
//stack.DestroyStack();//销毁栈
//stack.ClearStack();//将栈置为空栈
Boolean flag = stack.StackEmpty();//判断栈是否为空
int len = stack.StackLength();//返回栈的长度
stack.Push(3);//插入元素
stack.Push(4);
stack.Push(5);
int result1 = (int) stack.GetTop();//返回栈顶元素
int reslut2 = (int) stack.Pop();//弹出栈顶元素
stack.StackTraverse();//从栈底到栈顶依次对栈中每个元素调用函数visit()
}
}
栈的应用举例-括号匹配的检验
假设表达式中允许包括三种括号:{},[]和(),其嵌套的顺序随意,即([]{})或[({})]等为正确的格式,[(]或([{})或()]均为不正确的格式。问题则是:给出一段括号串,判断该括号串是否匹配?
这个问题我在LeetCode上遇到过,当时思考了很久,因为如果采用数组等数据结构解决这个问题的话,将十分麻烦,得嵌套遍历很多遍括号串才有可能解决该问题。所以,在想了很久后,突然想到了栈,因为栈可以随时弹出和插入元素,解决思路为:逐个遍历括号串,如果遇到左括号,则插入到栈中,如果遇到右括号时就需要判断该括号是否与栈顶的元素想匹配,如果匹配,则弹出栈顶元素,如果不匹配,则说明该括号串不匹配,下面的括号则无需遍历了。如果成功遍历完了所有括号,此时,如果栈中元素为空,则说明这段括号串匹配,否则,不匹配。由于只需遍历一遍括号串就可解决问题,所以时间复杂度为
O(n)
。下面则是我在LeetCode上写的代码(我是直接利用java.util包中的Stack来定义的栈):
import java.util.*;
/**
* Given a string containing just the characters '(', ')', '{', '}', '[' and ']', determine if the input string is valid.
The brackets must close in the correct order, "()" and "()[]{}" are all valid but "(]" and "([)]" are not.
*/
public class IsValid {
public boolean isValid(String s) {
// 1.获取每个字符
char[] characters = s.toCharArray();
// 2.如果为空,或者长度为奇数,则返回false
if(characters.length == 0 || (characters.length % 2) != 0)
return false;
// 3.定义一个栈,并遍历数组
Stack stack = new Stack();
for(int i = 0;i < characters.length;i++){
char c = characters[i];
if(c == '{' || c == '[' || c == '(')
stack.push(c);
else{
if(stack.empty())
return false;
char p = (char)stack.peek();
if((c == '}' && p == '{') || (c == ')' && p == '(') || (c == ']' && p == '['))
stack.pop();
else
return false;
}
}
if(stack.empty())
return true;
else
return false;
}
public static void main(String[] args) {
IsValid isValid = new IsValid();
Boolean flag = isValid.isValid("((");
System.out.println(flag);
}
}