数据结构与算法学习笔记(二)
栈的介绍
栈是一个先入后出的有序列表 栈是限制线性表中元素的插入和删除只能在线性表的同一端进行的一种特殊线性表。允许插入和删除的一端,为变化的一端,称为栈顶,另一端为固定的一端,称为栈底。 根据栈的定义可知,最先放入栈中元素在栈底,最后放入的元素在栈顶,,而删除元素刚好相反,最后放入的元素最先删除,最先放入的元素最后删除。
数组实现
public class ArrayStackDemo {
public static void main ( String [ ] args) {
ArrayStack stack = new ArrayStack ( 4 ) ;
String key = "" ;
boolean loop = true ;
Scanner scanner = new Scanner ( System . in) ;
while ( loop) {
System . out. println ( "show: 表示显示栈" ) ;
System . out. println ( "exit: 退出程序" ) ;
System . out. println ( "push: 表示添加数据到栈" ) ;
System . out. println ( "pop: 表示从栈取出数据" ) ;
System . out. println ( "请输入你的选择" ) ;
key = scanner. next ( ) ;
switch ( key) {
case "show" :
stack. list ( ) ;
break ;
case "push" :
System . out. println ( "请输入一个数" ) ;
int value = scanner. nextInt ( ) ;
stack. push ( value) ;
break ;
case "pop" :
try {
int res = stack. pop ( ) ;
System . out. printf ( "出栈的数据是%d\n" , res) ;
} catch ( Exception e) {
System . out. println ( e. getMessage ( ) ) ;
}
break ;
case "exit" :
scanner. close ( ) ;
loop = false ;
break ;
default :
break ;
}
}
System . out. println ( "程序退出" ) ;
}
}
class ArrayStack {
private int maxSize;
private int [ ] stack;
private int top = - 1 ;
public ArrayStack ( int maxSize) {
this . maxSize = maxSize;
stack = new int [ maxSize] ;
}
public boolean isFull ( ) {
return top == maxSize - 1 ;
}
public boolean isEmpty ( ) {
return top == - 1 ;
}
public void push ( int value) {
if ( isFull ( ) ) {
System . out. println ( "栈满" ) ;
return ;
}
top++ ;
stack[ top] = value;
}
public int pop ( ) {
if ( isEmpty ( ) ) {
throw new RuntimeException ( "栈空" ) ;
}
int value = stack[ top] ;
top-- ;
return value;
}
public void list ( ) {
if ( isEmpty ( ) ) {
System . out. println ( "栈空" ) ;
return ;
}
for ( int i = top; i >= 0 ; i-- ) {
System . out. printf ( "stack[%d]=%d\n" , i, stack[ i] ) ;
}
}
}
链表实现
public class StackTest {
public static void main ( String [ ] args) {
LinkedList linkedList = new LinkedList ( ) ;
Node node1 = new Node ( 1 ) ;
Node node2 = new Node ( 2 ) ;
Node node3 = new Node ( 3 ) ;
linkedList. push ( node1) ;
linkedList. push ( node2) ;
linkedList. push ( node3) ;
linkedList. list ( ) ;
System . out. println ( "出栈的编号:" + linkedList. pop ( ) . getData ( ) ) ;
linkedList. list ( ) ;
System . out. println ( "出栈的编号:" + linkedList. pop ( ) . getData ( ) ) ;
Node node4 = new Node ( 4 ) ;
linkedList. push ( node4) ;
linkedList. list ( ) ;
System . out. println ( "出栈的编号:" + linkedList. pop ( ) . getData ( ) ) ;
linkedList. list ( ) ;
System . out. println ( "出栈的编号:" + linkedList. pop ( ) . getData ( ) ) ;
linkedList. list ( ) ;
}
}
class LinkedList {
Node head = new Node ( - 1 ) ;
public void push ( Node node) {
if ( head. getNext ( ) != null ) {
node. setNext ( head. getNext ( ) ) ;
head. setNext ( node) ;
}
head. setNext ( node) ;
}
public Node pop ( ) {
if ( head. getNext ( ) == null ) {
return null ;
}
Node cur = head. getNext ( ) ;
head. setNext ( head. getNext ( ) . getNext ( ) ) ;
return cur;
}
public void list ( ) {
if ( head. getNext ( ) == null ) {
System . out. println ( "栈空" ) ;
return ;
}
Node cur = head. getNext ( ) ;
while ( cur != null ) {
System . out. println ( cur. getData ( ) ) ;
cur = cur. getNext ( ) ;
}
}
}
class Node {
private int data;
private Node next;
public Node ( int data) {
this . data = data;
}
public int getData ( ) {
return data;
}
public void setData ( int data) {
this . data = data;
}
public Node getNext ( ) {
return next;
}
public void setNext ( Node next) {
this . next = next;
}
}
栈实现综合计算器
public class Calculator {
public static void main ( String [ ] args) {
String expression = "12-9/3-2" ;
ArrayStack2 numStack = new ArrayStack2 ( 10 ) ;
ArrayStack2 operStack = new ArrayStack2 ( 10 ) ;
int index = 0 ;
int num1= 0 ;
int num2 = 0 ;
int oper = 0 ;
int res = 0 ;
char ch = ' ' ;
String keepNum = "" ;
while ( true ) {
ch = expression. substring ( index, index + 1 ) . charAt ( 0 ) ;
if ( operStack. isOper ( ch) ) {
if ( ! operStack. isEmpty ( ) ) {
while ( true ) {
if ( operStack. isEmpty ( ) || operStack. priority ( ch) > operStack. priority ( operStack. peek ( ) ) ) {
break ;
}
num1 = numStack. pop ( ) ;
num2 = numStack. pop ( ) ;
oper = operStack. pop ( ) ;
res = numStack. cal ( num1, num2, oper) ;
numStack. push ( res) ;
}
operStack. push ( ch) ;
} else {
operStack. push ( ch) ;
}
} else {
keepNum += ch;
if ( index == expression. length ( ) - 1 ) {
numStack. push ( Integer . parseInt ( keepNum) ) ;
} else {
if ( operStack. isOper ( expression. substring ( index + 1 , index + 2 ) . charAt ( 0 ) ) ) {
numStack. push ( Integer . parseInt ( keepNum) ) ;
keepNum = "" ;
}
}
}
index ++ ;
if ( index >= expression. length ( ) ) {
break ;
}
}
while ( true ) {
if ( operStack. isEmpty ( ) ) {
break ;
}
num1 = numStack. pop ( ) ;
num2 = numStack. pop ( ) ;
oper = operStack. pop ( ) ;
res = numStack. cal ( num1, num2, oper) ;
numStack. push ( res) ;
}
System . out. printf ( "表达式%s = %d" , expression, numStack. pop ( ) ) ;
}
}
class ArrayStack2 {
private int maxSize;
private int [ ] stack;
private int top = - 1 ;
public ArrayStack2 ( int maxSize) {
this . maxSize = maxSize;
stack = new int [ maxSize] ;
}
public int peek ( ) {
return stack[ top] ;
}
public boolean isFull ( ) {
return top == maxSize - 1 ;
}
public boolean isEmpty ( ) {
return top == - 1 ;
}
public void push ( int value) {
if ( isFull ( ) ) {
System . out. println ( "栈满" ) ;
return ;
}
top++ ;
stack[ top] = value;
}
public int pop ( ) {
if ( isEmpty ( ) ) {
throw new RuntimeException ( "栈空" ) ;
}
int value = stack[ top] ;
top-- ;
return value;
}
public void list ( ) {
if ( isEmpty ( ) ) {
System . out. println ( "栈空" ) ;
return ;
}
for ( int i = top; i >= 0 ; i-- ) {
System . out. printf ( "stack[%d]=%d\n" , i, stack[ i] ) ;
}
}
public int priority ( int oper) {
if ( oper == '*' || oper == '/' ) {
return 1 ;
} else if ( oper == '+' || oper == '-' ) {
return 0 ;
} else {
return - 1 ;
}
}
public boolean isOper ( char val) {
return val == '+' || val == '-' || val == '*' || val == '/' ;
}
public int cal ( int num1, int num2, int oper) {
int res = 0 ;
switch ( oper) {
case '+' :
res = num1 + num2;
break ;
case '-' :
res = num2 - num1;
break ;
case '*' :
res = num1 * num2;
break ;
case '/' :
res = num2 / num1;
break ;
default :
break ;
}
return res;
}
}
前缀表达式
前缀表达式又称波兰式,前缀表达式的运算符位于操作数之前 举例说明: (3+4)*5-6 对应的前缀表达式就是 - * + 3 4 5 6
中缀表达式
中缀表达式就是常见的运算表达式,如(3+4)*5-6 人熟悉,计算机不好操作,计算结果时一般转成后缀表达式(逆波兰表达式)
后缀表达式
后缀表达式又称逆波兰表达式,与前缀表达式类似,只是运算符位于操作数之后 举例说明:(3+4)*5-6 对应的后缀表达式就是 3 4 + 5 * 6 -
public class PolandNotation {
public static void main ( String [ ] args) {
String suffixExpression = "3 4 + 5 * 6 -" ;
List < String > list = getListString ( suffixExpression) ;
System . out. println ( "list=" + list) ;
int res = calculate ( list) ;
System . out. println ( "计算结果是=" + res) ;
}
public static List < String > getListString ( String suffixExpression) {
String [ ] split = suffixExpression. split ( " " ) ;
List < String > list = new ArrayList ( ) ;
for ( String ele : split) {
list. add ( ele) ;
}
return list;
}
public static int calculate ( List < String > ls) {
Stack < String > stack = new Stack < > ( ) ;
for ( String item : ls) {
if ( item. matches ( "\\d+" ) ) {
stack. push ( item) ;
} else {
int num2 = Integer . parseInt ( stack. pop ( ) ) ;
int num1 = Integer . parseInt ( stack. pop ( ) ) ;
int res = 0 ;
if ( item. equals ( "+" ) ) {
res = num1 + num2;
} else if ( item. equals ( "-" ) ) {
res = num1 - num2;
} else if ( item. equals ( "*" ) ) {
res = num1 * num2;
} else if ( item. equals ( "/" ) ) {
res = num1 / num2;
} else {
throw new RuntimeException ( "运算符有误" ) ;
}
stack. push ( res + "" ) ;
}
}
return Integer . parseInt ( stack. pop ( ) ) ;
}
}
中缀表达式转换为后缀表达式
初始化两个栈:运算符栈s1,和存储中间结果的栈s2 从左至右扫描中缀表达式 遇到操作数时,将其压s2 遇到运算符时,比较其与s1栈顶运算符的优先级
如果s1为空,或栈顶运算符为"(",则直接将此运算符入栈 否则,若优先级比栈顶运算符的高,也将运算符压入s1栈 否则,将s1栈顶的运算符弹出并压入到s2中,再次转到(4.1)与s1中新的栈顶运算符相比较 遇到括号时:
如果是左括号"(",则直接压入s1 如果是右括号")",则依次弹出s1栈顶的运算符,并压入s2,直到遇到左括号为止,此时将这一对括号丢弃 重复步骤2至5,直到表达式的最右边 将s1中剩余的运算符依次弹出并压入s2 依次弹出s2的元素并输出,结果的逆序即为中缀表达式对应的后缀表达式
public class PolandNotation {
public static void main ( String [ ] args) {
String expression = "1+((2+3)*4)-5" ;
List < String > list = toInfixExpressionList ( expression) ;
System . out. println ( "中缀表达式对应的list" + list) ;
List < String > list1 = parseSuffixExpreesionList ( list) ;
System . out. println ( "后缀表达式对应的list" + list1) ;
System . out. printf ( "expreesion=%d" , calculate ( list1) ) ;
/ * *
* 思路: 将表达式放入list,遍历list,配合栈完成计算
*
List < String > list = getListString ( suffixExpression) ;
System . out. println ( "list=" + list) ;
int res = calculate ( list) ;
System . out. println ( "计算结果是=" + res) ; * /
}
public static List < String > parseSuffixExpreesionList ( List < String > ls) {
Stack < String > s1 = new Stack < > ( ) ;
List < String > s2 = new ArrayList < > ( ) ;
for ( String item : ls) {
if ( item. matches ( "\\d+" ) ) {
s2. add ( item) ;
} else if ( item. equals ( "(" ) ) {
s1. push ( item) ;
} else if ( item. equals ( ")" ) ) {
while ( ! s1. peek ( ) . equals ( "(" ) ) {
s2. add ( s1. pop ( ) ) ;
}
s1. pop ( ) ;
} else {
while ( s1. size ( ) != 0 && Operation . getValue ( s1. peek ( ) ) >= Operation . getValue ( item) ) {
s2. add ( s1. pop ( ) ) ;
}
s1. push ( item) ;
}
}
while ( s1. size ( ) != 0 ) {
s2. add ( s1. pop ( ) ) ;
}
return s2;
}
public static List < String > toInfixExpressionList ( String s) {
List < String > ls = new ArrayList < > ( ) ;
int i = 0 ;
String str;
char c;
do {
if ( ( c = s. charAt ( i) ) < 48 || ( c = s. charAt ( i) ) > 57 ) {
ls. add ( "" + c) ;
i++ ;
} else {
str = "" ;
while ( i < s. length ( ) && ( c = s. charAt ( i) ) >= 48 && ( c = s. charAt ( i) ) <= 57 ) {
str += c;
i++ ;
}
ls. add ( str) ;
}
} while ( i < s. length ( ) ) ;
return ls;
}
public static List < String > getListString ( String suffixExpression) {
String [ ] split = suffixExpression. split ( " " ) ;
List < String > list = new ArrayList ( ) ;
for ( String ele : split) {
list. add ( ele) ;
}
return list;
}
public static int calculate ( List < String > ls) {
Stack < String > stack = new Stack < > ( ) ;
for ( String item : ls) {
if ( item. matches ( "\\d+" ) ) {
stack. push ( item) ;
} else {
int num2 = Integer . parseInt ( stack. pop ( ) ) ;
int num1 = Integer . parseInt ( stack. pop ( ) ) ;
int res = 0 ;
if ( item. equals ( "+" ) ) {
res = num1 + num2;
} else if ( item. equals ( "-" ) ) {
res = num1 - num2;
} else if ( item. equals ( "*" ) ) {
res = num1 * num2;
} else if ( item. equals ( "/" ) ) {
res = num1 / num2;
} else {
throw new RuntimeException ( "运算符有误" ) ;
}
stack. push ( res + "" ) ;
}
}
return Integer . parseInt ( stack. pop ( ) ) ;
}
}
class Operation {
private static int ADD = 1 ;
private static int SUB = 1 ;
private static int MUL = 2 ;
private static int DIV = 2 ;
public static int getValue ( String operation) {
int result = 0 ;
switch ( operation) {
case "+" :
result = ADD ;
break ;
case "-" :
result = SUB ;
break ;
case "*" :
result = MUL ;
break ;
case "/" :
result = DIV ;
break ;
default :
System . out. println ( "不存在该运算符" + operation) ;
break ;
}
return result;
}
}