上一篇博客我们实现了动态数组,今天我们对动态数组进行封装实习我们常用的数据结构栈。
//接口定义
public interface Stack<E> extends Iterable<E> {
public void push(E e);
public E pop();
public E peek();
public boolean isEmpty();
public int size();
public void clear();
}
public class ArrayStack<E> implements Stack<E> {
//使用动态数组实现栈
private ArrayList<E> list ;
public ArrayStack() {
list=new ArrayList<>();
}
@Override
public void push(E e) {
list.add(e);
}
@Override
public E pop() {
E ret=list.get(list.size()-1);
list.remove(list.size()-1);
return ret;
}
@Override
public E peek() {
return list.get(list.size()-1);
}
@Override
public boolean isEmpty() {
return list.isEmpty();
}
@Override
public int size() {
return list.size();
}
@Override
public void clear() {
list.clear();
}
@Override
public Iterator<E> iterator() {
return list.iterator();
}
@Override
public String toString() {
return list.toString();
}
}
我们来看看栈的常见应用
1.进制的转换
/**
* 该类主要使用栈实现进制转换的内容
* @author 上杉
*/
public class NumberSystemConversion {
public static void main(String[] args) {
int dec=65536;
String hex=decToHex(dec);
dec=hexToDec(hex);
System.out.println(hex);
System.out.println(dec);
}
private NumberSystemConversion() {
}
public static String decToHex(int dec) {
Stack<Integer> stack=new ArrayStack<>();
while(dec>0) {
stack.push(dec%16);
dec/=16;
}
StringBuilder res=new StringBuilder();
while(!stack.isEmpty()) {
int num=stack.pop();
if(num<10) {
res.append(num);
} else {
res.append('A'+num-10);
}
}
return res.toString();
}
public static int hexToDec(String hex) {
Stack<Integer> stack=new ArrayStack<>();
for(int i=0;i<hex.length();i++) {
char c=hex.charAt(i);
if(!(c>='0'&&c<='9'||c>='A'&&c<='F')) {
throw new IllegalArgumentException("wrong char "+c);
}
if(c>='0'&&c<='9') {
stack.push(c-'0');
}else {
stack.push(c-'A'+10);
}
}
int exponent =0;
int sum=0;
while(!stack.isEmpty()) {
sum+=stack.pop()*Math.pow(16,exponent);
exponent++;
}
return sum;
}
}
2.括号的匹配
/**
* 该类主要实现对一个只含有括号的字符串进行匹配
* @author 上杉
*/
public class BracketMatch {
public static void main(String[] args) {
String expression ="{[()<>]()}()[]";
Stack<Character> stack=new ArrayStack<>();
for(int i=0;i<expression.length();i++) {
char c=expression.charAt(i);
if(stack.isEmpty()||(c-stack.peek()!=1&&c-stack.peek()!=2)) {
stack.push(expression.charAt(i));
}else {
stack.pop();
}
}
if(stack.isEmpty()) {
System.out.println(expression + " 是匹配的");
}else {
System.out.println(expression + " 不是匹配的");
}
}
}
3.判断是否为回文串
//该类主要实现了一个字符串是否为回文串
//为了练习栈的使用所以这里采取栈实现,其实使用双指针效率更高一些
public class JudgingPalindrome {
public static void main(String[] args) {
String expression ="上海自来水来自海上";
Stack<Character> stack=new ArrayStack<>();
for(int i=0;i<expression.length();i++) {
if(expression.length()%2==1&&i==expression.length()/2) {
continue;
}else {
if(i<expression.length()/2) {
stack.push(expression.charAt(i));
}else {
if(stack.peek()!=expression.charAt(i)) {
break;
}
stack.pop();
}
}
}
if(stack.isEmpty()) {
System.out.println(expression+" 是回文串");
}else {
System.out.println(expression+" 不是回文串");
}
}
}
4.前缀中缀后缀表达式的计算与转换
(1)中缀表达式的计算
/**
*
* @author 上杉
*在表达式的计算范围栈的计算应用的非常广泛、
*本类主要使用栈来完成中缀表达式的计算
*/
public class InfixCalculator {
public static void main(String[] args) {
String infix="(5+2*4+4/2)/2+8-6";
int result=getResult(infix);
System.out.println(result);
}
private static int getResult(String infix) {
infix=expressionFormat(infix);
String[] spilt=infix.split(" ");
Stack<Character> opers=new ArrayStack<>();
Stack<Integer> nums=new ArrayStack<>();
for(String s:spilt) {
if(s.length()==0) {
continue;
}
if(s.charAt(0)=='(') {
opers.push(s.charAt(0));
} else if(s.charAt(0)==')') {
while(opers.peek()!='(') {
processAnOper(opers,nums);
}
opers.pop();
}else if(s.charAt(0)=='*'||s.charAt(0)=='/'){
while(!opers.isEmpty()&&(opers.peek()=='*'||opers.peek()=='/')) {
processAnOper(opers,nums);
}
opers.push(s.charAt(0));
}else if(s.charAt(0)=='+'||s.charAt(0)=='-') {
while(!opers.isEmpty()&&opers.peek()!='(') {
processAnOper(opers,nums);
}
opers.push(s.charAt(0));
}else {
nums.push(Integer.valueOf(s));
}
}
while(!opers.isEmpty()) {
processAnOper(opers,nums);
}
return nums.pop();
}
private static void processAnOper(Stack<Character> opers, Stack<Integer> nums) {
char oper=opers.pop();
int num1=nums.pop();
int num2=nums.pop();
switch(oper) {
case '+':
nums.push(num2+num1);
break;
case '-':
nums.push(num2-num1);
break;
case '*':
nums.push(num2*num1);
break;
case '/':
nums.push(num2/num1);
break;
}
}
public static String expressionFormat(String infix) {
StringBuilder res=new StringBuilder();
for(int i=0;i<infix.length();i++) {
char c=infix.charAt(i);
if(Character.isDigit(c)) {
res.append(c);
}else {
res.append(" ");
res.append(c);
res.append(" ");
}
}
return res.toString();
}
}
(2)中缀表达式转后缀表达式
public class InfixToSuffix {
public static void main(String[] args) {
String infix="(5+2*4+4/2)/2+8-6";
String suffix=getSuffix(infix);
System.out.println(suffix);
}
public static String getSuffix(String infix) {
infix=InfixCalculator.expressionFormat(infix);
String[] split=infix.split(" ");
Stack<Character> opers=new ArrayStack<>();
List<String> list =new ArrayList<>();
for(String s:split) {
if(s.length()==0) {
continue;
}
if(s.charAt(0)=='(') {
opers.push(s.charAt(0));
}else if(s.charAt(0)==')') {
while(opers.peek()!='(') {
list.add(opers.pop()+"");
}
opers.pop();
}else if(s.charAt(0)=='+'||s.charAt(0)=='-') {
while(!opers.isEmpty()&&opers.peek()!='(') {
list.add(opers.pop()+"");
}
opers.push(s.charAt(0));
}else if(s.charAt(0)=='*'||s.charAt(0)=='/') {
while(!opers.isEmpty()&&(opers.peek()=='*'||opers.peek()=='/')) {
list.add(opers.pop()+"");
}
opers.push(s.charAt(0));
}else {
list.add(s);
}
}
while(!opers.isEmpty()) {
list.add(opers.pop()+"");
}
StringBuilder str=new StringBuilder();
for(String s:list) {
str.append(s+" ");
}
return str.toString();
}
}
(3)后缀表达式的计算
public class SuffixCalculator {
public static void main(String[] args) {
String suffix="5 2 4 * + 4 2 / + 2 / 8 + 6 - ";
int res=getResult(suffix);
System.out.println(res);
}
public static int getResult(String suffix) {
String[] spilt=suffix.split(" ");
Stack<Integer> nums=new ArrayStack<>();
for(String s:spilt) {
if(s.length()==0) {
continue;
}
if(s.charAt(0)=='+'||s.charAt(0)=='-'||s.charAt(0)=='*'||s.charAt(0)=='/') {
processAnOper( s.charAt(0) , nums);
}else {
nums.push(Integer.valueOf(s));
}
}
return nums.pop();
}
private static void processAnOper(char oper,Stack<Integer> nums) {
int num1=nums.pop();
int num2=nums.pop();
switch(oper) {
case '+':
nums.push(num2+num1);
break;
case '-':
nums.push(num2-num1);
break;
case '*':
nums.push(num2*num1);
break;
case '/':
nums.push(num2/num1);
break;
}
}
}