数据结构 栈 (JAVA语言描述)
栈(stack)是限定仅在表尾进行插入或者删除的线性表。对于栈来说,表尾端称为栈顶(top),表头端称为栈低(bottom)。不含元素的空表称为空栈。因为栈限定在表尾进行插入或者删除,所以栈又被称为后进先出的线性表
一些关于栈的方法及实现
大部分直接调用线性表的方法即可
@Override
public int size() {
return list.size();
}
@Override
public boolean isEmpty() {
return list.isEmpty();
}
@Override
public void push(E element) {
list.add(element);
}
@Override
public E pop() {
return list.remove(list.size()-1);
}
@Override
public E peek() {
return list.get(list.size()-1);
}
@Override
public void clear() {
list.clear();
}
@Override
public Iterator<E> iterator() {
return list.iterator();
}
中缀表达式的计算
- 从左到右扫描,如果扫描到的运算符优先级大于栈顶运算符优先级,则入栈,否则,出栈并运算。
- 如果遇到右括号,一直出栈,直到遇到左括号为止。并且每一次出栈的运算符都要做一次运算。
- 扫描完整个表达式后,S2栈中如果还有运算符剩余,则全部出栈,逐个计算即可。
public class InfixCalculator {
public static void main(String[] args) {
String s ="(10+20/2*3)/2+8";
System.out.println(s);
int res = evaluateString(s);
System.out.println(res);
}
private static int evaluateString(String s){
s= insertBlanks(s);
String[] tokens = s.split(" ");
ArrayStack<Character> operatorStack =new ArrayStack<>();
ArrayStack<Integer> numberStack =new ArrayStack<>();
for (String token: tokens) {
if(token.length()==0){ //过滤空串
continue;
//遍历到加减号
}else if (token.equals("+")||token.equals("-")){
while (!operatorStack.isEmpty()&&(operatorStack.peek() == '+'|| operatorStack.peek() == '-'||operatorStack.peek() == '*'||operatorStack.peek()=='/')){
//之前是 + - * / 需要弹栈 计算
processAnOperator(numberStack,operatorStack);
}
//如果操作符栈为空 或者不为空 但栈顶为 (
operatorStack.push((token.charAt(0)));
}else if (token.equals("*")||token.equals("/")){ //遍历到乘除
while (!operatorStack.isEmpty()&&(operatorStack.peek() == '*'||operatorStack.peek()=='/')){
processAnOperator(numberStack,operatorStack);
}
operatorStack.push((token.charAt(0)));
}else if (token.equals("(")){
operatorStack.push((token.charAt(0)));
}else if (token.equals(")")){
//只要操作符栈顶不是(挨个弹栈计算
while (operatorStack.peek()!='('){
processAnOperator(numberStack,operatorStack);
}
operatorStack.pop();
}else {
numberStack.push(new Integer(token));
}
}
while (!operatorStack.isEmpty()){
processAnOperator(numberStack,operatorStack);
}
return numberStack.pop();
}
private static void processAnOperator(ArrayStack<Integer>numStack,ArrayStack<Character>operatorStack){
char op=operatorStack.pop();
int num1 =numStack.pop();
int num2 =numStack.pop();
if (op == '-') {
numStack.push(num2-num1);
}else if (op=='+'){
numStack.push(num2+num1);
}else if (op =='*'){
numStack.push(num2*num1);
}else if(op=='/'){
numStack.push(num2/num1);
}
}
//给所有非数字符号两边添加空格
public static String insertBlanks(String S){
StringBuilder sb = new StringBuilder();
for(int i =0;i< S.length();i++){
char c = S.charAt(i);
if (c =='/'||c=='*'||c=='('||c==')'||c=='-'||c=='+'){
sb.append(' ');
sb.append(c);
sb.append(' ');
}else {
sb.append(c);
}
}
return sb.toString();
}
- 中缀转后缀
public static String infixTosuffix(String s) {
s= insertBlanks(s);
String[] tokens = s.split(" ");
//操作符的栈
ArrayStack<String> opStack = new ArrayStack<>();
//后缀表达式的线性表
ArrayList<String> suffixList = new ArrayList<>();
for (String token: tokens) {
if (token.length()==0){
continue;
}
//判断操作符
if (isOperator(token)){
/*
如果栈为空进栈 栈顶为 ( 进栈 栈顶的操作符优先级比token小
栈顶的优先级大于等于token出栈
*/
while (true){
if (opStack.isEmpty()||opStack.peek().equals("(")||priority(opStack.peek())<priority(token)){
opStack.push(token);
break;
}
suffixList.add(opStack.pop());
}
}else if (token.equals("(")){
opStack.push(token);
}else if (token.equals(")")){
while (!opStack.peek().equals("(")){
suffixList.add(opStack.pop());
}
opStack.pop();
}else if (isNumber(token)){
suffixList.add(token);
}else {
throw new IllegalArgumentException("wrong char");
}
}
while (!opStack.isEmpty()){
suffixList.add(opStack.pop());
}
StringBuilder sb = new StringBuilder();
for (int i =0;i<suffixList.size();i++){
sb.append(suffixList.get(i));
sb.append(' ');
}
return sb.toString();
}
private static int priority(String token) {
if (token.equals("+")||token.equals("-")){
return 0;
}
if (token.equals("*")||token.equals("/")){
return 1;
}
return -1;
}
private static boolean isNumber(String token) {
return token.matches("\\d+");
}
private static boolean isOperator(String token) {
return token.equals("+")||token.equals("-")||token.equals("*")||token.equals("/");
}
//给所有非数字符号两边添加空格
public static String insertBlanks(String S){
StringBuilder sb = new StringBuilder();
for(int i =0;i< S.length();i++){
char c = S.charAt(i);
if (c =='/'||c=='*'||c=='('||c==')'||c=='-'||c=='+'){
sb.append(' ');
sb.append(c);
sb.append(' ');
}else {
sb.append(c);
}
}
return sb.toString();
}
}
- 后缀计算器
public class SufixCalculator {
public static void main(String[] args) {
String s ="(10+20/2*3)/2+8";
String c = InfixTosuffix.infixTosuffix(s);
int res = evaluateSuffix(c);
System.out.println(res);
}
private static int evaluateSuffix(String c) {
ArrayStack<Integer> stack = new ArrayStack<>();
String[] tokens= c.split(" ");
for (String token: tokens) {
if (token.length()==0){
continue;
}
if (isNumber(token)){
stack.push(new Integer((token)));
}else {
processAnOperator(stack,token);
}
}
return stack.pop();
}
private static void processAnOperator(ArrayStack<Integer> stack, String token) {
int num1 = stack.pop();
int num2 =stack.pop();
if (token.equals("+")){
stack.push(num2+num1);
}else if (token.equals("-")){
stack.push(num2-num1);
}else if (token.equals("*")){
stack.push(num2*num1);
}else if (token.equals("/")){
stack.push(num2/num1);
}
}
private static boolean isNumber(String token) {
return token.matches("\\d+");
}
}
- 进制转换
十进制转十六进制
public class DecToHex {
public static void main(String[] args) {
int num=654321;
ArrayStack<String> stack = new ArrayStack<>();
while (num!=0){
int a = num%16;
if (a<10){
stack.push(a+"");
}else {
stack.push((char)(a-10+'A')+"");
}
num/=16;
}
StringBuilder sb = new StringBuilder();
while (!stack.isEmpty()){
sb.append(stack.pop());
}
System.out.println(sb.toString());
}
}
十六进制转十进制
public class HexToDec {
public static void main(String[] args) {
String hex ="9FBF1";
ArrayStack<Character> stack = new ArrayStack<>();
for (int i = 0;i<hex.length();i++){
stack.push(hex.charAt(i));
}
int sum =0;
int mi=0;
while (!stack.isEmpty()){
char c = stack.pop();
sum+=getNumber(c)*Math.pow(16,mi);
mi++;
}
System.out.println(sum);
}
private static int getNumber(char c) {
if (!(c>='0'&&c<='9'||c>='A'&&c<='F')){
throw new IllegalArgumentException("wrong char");
}
if (c>='0'&&c<='9'){
return c-'0';
}else {
return c-'A'+10;
}
}
}
- 判断回文串
用栈和双指针实现
public class Judging {
public static void main(String[] args) {
String text = "1234321";
ArrayStack<Character> stack = new ArrayStack<>();
//1 栈
for (int i=0;i<text.length();i++){
if (text.length()%2==1&&i==text.length()/2){
continue;
}
char c =text.charAt(i);
if (stack.isEmpty()){
stack.push(text.charAt(i));
}else {
if (c!=stack.peek()){
stack.push(c);
}else {
stack.pop();
}
}
}
System.out.println(stack.isEmpty());
//2 双指针
int i =0;
int j =text.length()-1;
while (true){
if (text.charAt(i)==text.charAt(j)){
i++;
j--;
}else {
System.out.println("No");
break;
}
if (j<=i){
System.out.println("Yes");
break;
}
}
}
}