欢迎关注我的B站账号:卍卍子非鱼卍卍
栈&队列
栈
栈节点StackNode
class StackNode<T> {
public T val;
public StackNode<T> next;
public StackNode() {
this(null);
}
public StackNode(T val) {
this.val = val;
this.next = null;
}
}
栈类型MyStack
boolean isEmpty()
判断栈是否为空
void push(T e)
元素进栈
T pop()
栈顶元素出栈
T peek()
取栈顶元素
String toString()
打印栈
class MyStack<T> {
StackNode<T> head;
public MyStack() {
head = new StackNode<T>();
}
// 判断栈是否为空
public boolean isEmpty() {
return head.next == null;
}
// 元素进栈
public void push(T e) {
StackNode<T> p = new StackNode<T>(e);
p.next = head.next;
head.next = p;
}
// 栈顶元素出栈
public T pop() {
if (this.isEmpty()) {
throw new NullPointerException();
}
T val = head.next.val;
head.next = head.next.next;
return val;
}
// 取栈顶元素
public T peek() {
if (this.isEmpty()) {
throw new NullPointerException();
}
T val = head.next.val;
return val;
}
// 打印栈
public String toString() {
if (this.isEmpty()) {
return "";
}
String str = "";
StackNode<T> node = head;
while (node.next.next != null) {
node = node.next;
str += node.val + "->";
}
str += node.next.val;
return str;
}
}
队列
队列节点QueueNode
class QueueNode<T> {
public T val;
public QueueNode<T> next;
public QueueNode() {
this(null);
}
public QueueNode(T val) {
this.val = val;
this.next = null;
}
}
队列类型MyQueue
boolean isEmpty()
判断队列是否为空
void offer(T e)
元素进队
T poll()
元素出队
T element()
取队首元素
String toString()
打印队列
class MyQueue<T> {
QueueNode<T> head;
QueueNode<T> tail;
public MyQueue() {
head = null;
tail = null;
}
// 判断队列是否为空
public boolean isEmpty() {
return tail == null;
}
// 元素进队
public void offer(T e) {
QueueNode<T> node = new QueueNode<T>(e);
if (this.isEmpty()) {
head = node;
tail = node;
} else {
tail.next = node;
tail = tail.next;
}
}
// 元素出队
public T poll() {
if (this.isEmpty()) {
throw new NullPointerException();
}
T val = head.val;
if (head == tail) {
head = null;
tail = null;
} else {
head = head.next;
}
return val;
}
// 取队首元素
public T element() {
if (this.isEmpty()) {
throw new NullPointerException();
}
return head.val;
}
// 打印队列
public String toString() {
if (this.isEmpty()) {
return "";
}
QueueNode<T> node = head;
String str = "[";
while (node.next != null) {
str += node.val + ", ";
node = node.next;
}
str += node.val + "]";
return str;
}
}
中缀表达式转后缀表达式
输入中缀表达式字符串形式,输出后缀表达式数组形式
算法思路
后缀表达式:又名逆波兰式,运算符写在操作数之后
中缀表达式:按照正常写法的计算式
现有如下中缀表达式:“(56 + 20) / (2 * 4)”
将其转化为后缀表达式的数组形式:["56", "20", "+", "2", "4", "*", "/"]
思路如下:
1.定义List<String> suffix
用于存储中缀表达式, 定义MyStack<String> stack
用于暂时存储运算符
2.从左到右以字符ch
形式读取字符串:
2.1 若ch
为数字,一直读取直到不是数字为止,将该数字加入suffix
2.2 若ch
为(
,将(
进栈到stack
2.3 若ch
为)
,将stack
中的元素依次出栈并加入suffix
,直到栈顶元素为(
,然后将(
出栈
2.4 若ch
为+
,-
,将stack
中的元素依次出栈并加入suffix
,直到栈顶元素为(
或栈空,然后将ch
进栈
2.5 若ch
为*
,/
,将stack
中的元素依次出栈并加入suffix
,直到栈顶元素为(
,+
,-
或栈空,然后将ch
进栈
3.字符串读取完毕后,将stack
中的元素依次出栈并加入suffix
以表达式“(56 + 20) / (2 * 4)”
为例,最后后缀表达式形式:["56", "20", "+", "2", "4", "*", "/"]
:
代码
import java.util.*;
class Solution_1 {
/**
* 中缀表达式转后缀表达式
*
* @param Infix 中缀表达式
* @return 后缀表达式的数组形式
*/
public String[] InfToSuf(String infix) {
List<String> suffix = new ArrayList<String>();
MyStack<String> stack = new MyStack<String>();
for (int i = 0; i < infix.length(); i++) {
int j = i + 1;
String regex = "^-?\\d+$";
while (j <= infix.length() && infix.substring(i, j).matches(regex)) {
j++;
}
if (j > i + 1) {
String num = infix.substring(i, j - 1);
suffix.add(num);
i = j - 2;
} else {
String str = infix.substring(i, i + 1);
switch (str) {
case "(":
stack.push(str);
break;
case ")":
while (!stack.peek().equals("(")) {
suffix.add(stack.pop());
}
stack.pop();
break;
case "+":
case "-":
while (!stack.isEmpty() && !stack.peek().equals("(")) {
suffix.add(stack.pop());
}
stack.push(str);
break;
case "*":
case "/":
while (!stack.isEmpty() && !stack.peek().equals("(") && !stack.peek().equals("+")
&& !stack.peek().equals("-")) {
suffix.add(stack.pop());
}
stack.push(str);
break;
}
}
}
while (!stack.isEmpty()) {
suffix.add(stack.pop());
}
String[] array = new String[suffix.size()];
suffix.toArray(array);
return array;
}
}
后缀表达式求值
输入后缀表达式的数组形式,输出求得的值(整数形式)
算法思路
现有上一题求出的后缀表达式数组形式suffix
:["56", "20", "+", "2", "4", "*", "/"]
计算它的值
思路如下:
1.定义MyStack<Integer> stack
用作临时存储
2.以字符串str
形式遍历suffix
:
2.1 若str
为数字,将str
入栈
2.2 若str
为运算符op
(其中op
可以表示"+","-","*","/"
),连续出栈两个数值a,b
,计算b op a
,并入栈
3.遍历结束,返回栈顶元素stack.peek()
以后缀表达式["56", "20", "+", "2", "4", "*", "/"]
为例:
代码
class Solution_2 {
/**
* 后缀表达式求值
*
* @param suffix 后缀表达式的数组形式
* @return 求得的值(整数形式)
*/
public int evalSuf(String[] suffix) {
MyStack<Integer> stack = new MyStack<Integer>();
String regex = "^-?\\d+$";
for (String str : suffix) {
if (str.matches(regex)) {
stack.push(Integer.parseInt(str));
} else {
int num1 = stack.pop(), num2 = stack.pop();
switch (str) {
case "+":
num2 += num1;
break;
case "-":
num2 -= num1;
break;
case "*":
num2 *= num1;
break;
case "/":
num2 /= num1;
break;
}
stack.push(num2);
}
}
return stack.pop();
}
}
验证回文串
输入待验证的字符串,是回文串返回true,否则返回false
算法思路
回文串特征:从左到右读与从右到左读各个字符相同
如:aabbaa
是回文串,aaaa
是回文串,abcabc
不是回文串
思路如下:
1.定义MyStack<Character> stack
用于存储字符
2.以字符ch
形式顺序读取字符串str
,将ch
入栈
3.将栈内元素依次出栈,并与顺序读取的字符ch
比较,若两者不相等,说明不是回文串,返回false
4.栈空说明所有字符均满足回文串特征,返回true
代码
class Solution_3 {
/**
* 验证字符串是否为回文串
*
* @param str 待验证的字符串
* @return 是回文串返回true,否则返回false
*/
public boolean isPalindrome(String str) {
MyStack<Character> stack = new MyStack<Character>();
for (char ch : str.toCharArray()) {
stack.push(ch);
}
for (char ch : str.toCharArray()) {
if (ch != stack.pop()) {
return false;
}
}
return true;
}
}