括号匹配问题 问题描述:
分析: 创建一个栈用来存储左括号 从左往右遍历字符串,拿到每一个字符 判断该字符是不是左括号,如果是,放入栈中存储 判断该字符是不是右括号,如果不是,继续下一次循环 如果该字符是右括号,则从栈中弹出一个元素t; 判断元素t是否为null,如果不是,则证明有对应的左括号,如果不是,则证明没有对应的左括号 循环结束后,判断栈中还有没有剩余的左括号,如果有,则不匹配,如果没有,则匹配 代码实现: 栈 Stack: import java. util. Iterator ; public class Stack < T > implements Iterable < T > { //记录首结点 private Node head; //栈中元素的个数 private int N ; private class Node { public T item; public Node next; public Node ( T item, Node next) { this . item= item; this . next= next; } } public Stack ( ) { this . head= new Node ( null , null ) ; this. N= 0 ; } //判断当前栈中元素个数是否为0 public boolean isEmpty ( ) { return N == 0 ; } //获取栈中元素的个数 public int size ( ) { return N ; } //把t元素压入栈 public void push ( T t) { //找到首结点指向的第一个结点 Node oldFirst= head. next; //创建新结点 Node newNode= new Node ( t, null ) ; //让首结点指向新结点 head. next= newNode; //让新结点指向原来的第一个结点 newNode. next= oldFirst; //元素个数+1; N ++ ; } //弹出栈顶元素 public T pop ( ) { //找到首结点指向的第一个结点 Node oldFirst= head. next; if ( oldFirst== null ) { return null ; } //让首结点指向原来第一个结点的下一个结点 head. next= oldFirst. next; //元素个数-1; N -- ; return oldFirst. item; } @Override public Iterator < T > iterator ( ) { return new SIterator ( ) ; } private class SIterator implements Iterator { private Node n; public SIterator ( ) { this . n= head; } @Override public boolean hasNext ( ) { return n. next!= null ; } @Override public Object next ( ) { n= n. next; return n. item; } } } 匹配方法 isMatch(): /** * 判断str中的括号是否匹配 * @param str 括号组成的字符串 * @return 如果匹配,返回true,如果不匹配,返回false */ public static boolean isMatch ( String str) { //1.创建栈对象,用来存储左括号 Stack < String > chars= new Stack < > ( ) ; //2.从左往右遍历字符串 for ( int i= 0 ; i< str. length ( ) ; i++ ) { String currChar= str. charAt ( i) + "" ; //3.判断当前字符是否为左括号,如果是,则把字符放入到栈中 if ( currChar. equals ( "(" ) ) { chars. push ( currChar) ; } else if ( currChar. equals ( ")" ) ) { //4.继续判断当前字符是否是有括号,如果是,则从栈中弹出一个左括号,并判断弹出的结果是否为null,如果为null证明没有匹配的左括号,如果不为null,则证明有匹配的左括号 String pop= chars. pop ( ) ; if ( pop== null ) { return false ; } } } //5.判断栈中还有没有剩余的左括号,如果有,则证明括号不匹配 if ( chars. size ( ) == 0 ) { return true ; } else { return false ; } } 测试: public static void main ( String [ ] args) { String str= "上海(长安)())" ; boolean match= isMatch ( str) ; System . out. println ( str+ "中的括号是否匹配:" + match) ; }
逆波兰表达式求值问题 逆波兰表达式求值问题是我们计算机中经常遇到的一类问题,要研究明白这个问题,首先我们得搞清楚什么是逆波兰表达式?要搞清楚逆波兰表达式,我们得从中缀表达式说起。 中缀表达式: 中缀表达式就是我们平常生活中使用的表达式,例如:1+3*2,2-(1+3)等等,中缀表达式的特点是:二元运算符总是置于两个操作数中间 。 中缀表达式是人们最喜欢的表达式方式,因为简单,易懂。但是对于计算机来说就不是这样了,因为中缀表达式的运算顺序不具有规律性。不同的运算符具有不同的优先级,如果计算机执行中缀表达式,需要解析表达式语义,做大量的优先级相关操作 。 逆波兰表达式(后缀表达式): 逆波兰表达式是波兰逻辑学家J・卢卡西维兹(J・ Lukasewicz)于1929年首先提出的一种表达式的表示方法,后缀表达式的特点:运算符总是放在跟它相关的操作数之后 。 需求: 给定一个只包含加减乘除四种运算的逆波兰表达式的数组表示方式,求出该逆波兰表达式的结果。 分析:
代码实现: 栈 Stack: import java. util. Iterator ; public class Stack < T > implements Iterable < T > { //记录首结点 private Node head; //栈中元素的个数 private int N ; private class Node { public T item; public Node next; public Node ( T item, Node next) { this . item= item; this . next= next; } } public Stack ( ) { this . head= new Node ( null , null ) ; this. N= 0 ; } //判断当前栈中元素个数是否为0 public boolean isEmpty ( ) { return N == 0 ; } //获取栈中元素的个数 public int size ( ) { return N ; } //把t元素压入栈 public void push ( T t) { //找到首结点指向的第一个结点 Node oldFirst= head. next; //创建新结点 Node newNode= new Node ( t, null ) ; //让首结点指向新结点 head. next= newNode; //让新结点指向原来的第一个结点 newNode. next= oldFirst; //元素个数+1; N ++ ; } //弹出栈顶元素 public T pop ( ) { //找到首结点指向的第一个结点 Node oldFirst= head. next; if ( oldFirst== null ) { return null ; } //让首结点指向原来第一个结点的下一个结点 head. next= oldFirst. next; //元素个数-1; N -- ; return oldFirst. item; } @Override public Iterator < T > iterator ( ) { return new SIterator ( ) ; } private class SIterator implements Iterator { private Node n; public SIterator ( ) { this . n= head; } @Override public boolean hasNext ( ) { return n. next!= null ; } @Override public Object next ( ) { n= n. next; return n. item; } } } 计算方法: caculate /** * @param notaion 逆波兰表达式的数组表示方式 * @return 逆波兰表达式的计算结果 */ public static int caculate ( String [ ] notaion) { //1.定义一个栈,用来存储操作数 Stack < Integer > oprands= new Stack < > ( ) ; //2.从左往右遍历逆波兰表达式,得到每一个元素 for ( int i= 0 ; i< notaion. length; i++ ) { String curr= notaion[ i] ; //3.判断当前元素是运算符还是操作数 Integer o1; Integer o2; Integer result; switch ( curr) { case "+" : //4.运算符,从栈中弹出两个操作数,完成运算,运算完的结果再压入栈中 o1= oprands. pop ( ) ; o2= oprands. pop ( ) ; result= o2+ o1; oprands. push ( result) ; break ; case "-" : //4.运算符,从栈中弹出两个操作数,完成运算,运算完的结果再压入栈中 o1= oprands. pop ( ) ; o2= oprands. pop ( ) ; result= o2- o1; oprands. push ( result) ; break ; case "*" : //4.运算符,从栈中弹出两个操作数,完成运算,运算完的结果再压入栈中 o1= oprands. pop ( ) ; o2= oprands. pop ( ) ; result= o2* o1; oprands. push ( result) ; break ; case "/" : //4.运算符,从栈中弹出两个操作数,完成运算,运算完的结果再压入栈中 o1= oprands. pop ( ) ; o2= oprands. pop ( ) ; result= o2/ o1; oprands. push ( result) ; break ; default : //5.操作数,把该操作数放入到栈中; oprands. push ( Integer . parseInt ( curr) ) ; break ; } } //6.得到栈中最后一个元素,就是逆波兰表达式的结果 int result= oprands. pop ( ) ; return result; } 测试: 中缀表达式 3*(17-15)+18/6 逆波兰表达式 3,17,15,-,*,18,6,/,+ 计算结果 6+3=9 public static void main ( String [ ] args) { //中缀表达式 3*(17-15)+18/6 的逆波兰表达式如下 6+3=9 String [ ] notation= { "3" , "17" , "15" , "-" , "*" , "18" , "6" , "/" , "+" } ; int result= caculate ( notation) ; System . out. println ( "逆波兰表达式的结果为:" + result) ; }