提示:看之前请先学习链表知识点
boolean empty( )
——如果堆栈是空的,则返回true,当堆栈包含元素时,返回false。
Object peek( )
———–返回位于栈顶的元素,但是并不在堆栈中删除它。
Object pop( )
————返回位于栈顶的元素,并在进程中删除它。
Object push (Object element )
———将element压入堆栈,同时也返回element。
int search(Object element)
———在堆栈中搜索element,如果发现了,则返回它相对于栈顶
的偏移量。否则,返回-1。
package com.gdpu.Stack;
import LinkedList.ListNode;
import java.util.Iterator;
/**
* 用链表实现栈
* 头部节点不放数据
* head的指向的第一个节点就是栈顶
*/
public class Stack<T> implements Iterable{
//记录首结点
private ListNode head;
//栈中元素的个数
private int N;
public Stack() {
this.head = new ListNode(null,null);
this.N=0;
}
//判断当前栈中元素个数是否为0
public boolean isEmpty(){
return N==0;
}
//获取栈中元素的个数
public int size(){
return N;
}
//把t元素压栈
public void push(T t){
//找到首结点指向的第一个结点
ListNode oldFirst = head.next;
//创建新结点
ListNode newNode = new ListNode(t, null);
//让首结点指向新结点
head.next = newNode;
//让新结点指向原来的第一个结点
newNode.next=oldFirst;
//元素个数+1;
N++;
}
//弹出栈顶元素
//返回位于栈顶的元素,并在进程中删除它
public T pop(){
//找到首结点指向的第一个结点
ListNode oldFirst = head.next;
if (oldFirst==null){
return null;
}
//让首结点指向原来第一个结点的下一个结点
head.next=oldFirst.next;
//元素个数-1;
N--;
return (T) oldFirst.val;
}
//返回位于栈顶的元素,但是并不在堆栈中删除它。
public T peek(){
//找到首结点指向的第一个结点
ListNode oldFirst = head.next;
if (oldFirst==null){
return null;
}
return (T) oldFirst.val;
}
@Override
public Iterator<T> iterator() {
return new SIterator();
}
private class SIterator implements Iterator{
private ListNode n;
public SIterator(){
this.n=head;
}
@Override
public boolean hasNext() {
return n.next!=null;
}
@Override
public Object next() {
n = n.next;
return n.val;
}
}
}
队列(Queue)
:简称队。是一种操作受限的线性表,只允许在表的一端进行插入,而在表的另一端进行删除。向队列中插入元素称为入队或进队;删除元素称为出队或离队。其操作特性为先进先出(First In First Out,FIFO),并且只允许在队尾进,队头出。
队头(Front)
:允许删除的一端,又称队首
队尾(Rear)
:允许插入的一端
空队列
:不包含任何元素的空表
Queue<Integer> queue1 = new LinkedList<Integer>();
方法 | 作用 |
---|---|
add() | 入队(若失败则抛出IllegalStateException异常) |
offer() | 将指定元素插入队列,成功返回true,否则返回false |
element() | 获取队头的值,但不出队(若队列为空则抛出异常NoSuchElementException) |
peek() | 获取队头的值,但不出队(若队列为空则返回null |
poll() | 获取并移除队头(若队列空则返回null) |
remove | 获取并移除队头(若队列空则抛出NoSuchElementException异常) |
package Queue;
import LinkedList.ListNode;
import java.util.Iterator;
/**
* 用链表实现的队列
* @param
*/
public class LinkQueue<T> implements Iterable<T> {
// 队头
private ListNode front;
// 队尾
private ListNode rear;
// 元素个数
private int size;
/**
* 创建队列
*/
public LinkQueue() {
rear = front = null;
size=0;
}
/**
* 入队列
*
* @param data
*/
public void offer(T data) {
ListNode<T> node = new ListNode<T>(data);
//如果是空队列
if (isEmpty()) {
front = rear = node;
} else {
//在尾部插入
rear.next = node;
rear = node;
}
size++;
}
/**
* 出队列
* @return 返回数据
*/
public T poll() {
if (isEmpty()) {
throw new RuntimeException("队列为空");
}
ListNode<T> delete = front;
//更改头部节点
front = delete.next;
delete.next=null; // help GC
//数量减1
size--;
if (size == 0) {
// 删除掉最后一个元素时,front值已经为null,但rear还是指向该节点,需要将rear置为null
// 最后一个结点front和rear两个引用都没指向它,帮助GC处理该节点对象
rear = front;
}
return (T) delete.val;
}
/**
* 只取队列头的数据
*/
public T peek(){
if (isEmpty()) {
throw new RuntimeException("队列为空");
}
return (T) front.val;
}
/**
* 判断队列是否为空
*/
public boolean isEmpty() {
return front == null && rear == null;
}
/**
* 获取队列的元素个数
*/
public int size() {
return this.size;
}
//自己添加遍历模块
@Override
public Iterator<T> iterator() {
return new QIterator();
}
private class QIterator implements Iterator{
private ListNode n = new ListNode();
public QIterator(){
n.next=front;
}
@Override
public boolean hasNext() {
return n.next!=null;
}
@Override
public Object next() {
n = n.next;
return n.val;
}
}
}
package com.gdpu.day1;
public class NO_844_backspaceCompare {
public boolean backspaceCompare(String S, String T) {
return transfer(S).equals(transfer(T));
}
/**
* 暴力遍历
* 翻译出按规则的最后的字符串
*/
public String transfer(String str){
StringBuffer ret = new StringBuffer();
for (int i =0;i<str.length();i++){
char ch = str.charAt(i);
if (ch!='#'){
ret.append(ch);
}else {
if (ret.length()>0){
ret.deleteCharAt(ret.length()-1);
}
}
}
return ret.toString();
}
}
/**
* 两个指针分别逆向遍历两个字符串
*/
public boolean doublePointCompare(String S, String T) {
int i = S.length() - 1;
int j = T.length() - 1;
int skipS = 0, skipT = 0;
while (i > 0 || j > 0) {
while (i >= 0) {
if (S.charAt(i) == '#') {
skipS++;
} else if (skipS > 0) {
skipS--;
i--;
} else {
//找到一个无法消除的了,跳出
break;
}
}
while (j >= 0) {
if (T.charAt(j) == '#') {
skipT++;
} else if (skipT > 0) {
skipS--;
j--;
} else {
//找到一个无法消除的了,跳出
break;
}
}
//如果两步的索引都是大于等于0
if (i >= 0 && j >= 0) {
//如果此时双方无法消除的不相等
if (S.charAt(i) != T.charAt(j)) {
return false;
}
} else {
//排除了都是大于等于0,如果有一个是大于等于0
if (i >= 0 || j >= 0) {
return false;
}
}
i--;
j--;
}
return true;
}
class Solution {
public boolean isValid(String s) {
int n = s.length();
//如果是奇数,必然是不能匹配完全
if (n % 2 == 1) {
return false;
}
//定义一个映射map
Map<Character, Character> pairs = new HashMap<Character, Character>() {
{
put(')', '(');
put(']', '[');
put('}', '{');
}};
Stack<Character> stack = new Stack<Character>();
for (int i = 0;i<n;i++){
char ch = s.charAt(i);
//如果是右括号
if (pairs.containsKey(ch)){
//此时如果栈是空的或者栈顶元素不匹配则返回false
if (stack.isEmpty() || stack.peek() != pairs.get(ch)) {
return false;
}
//匹配成功弹出栈顶元素
stack.pop();
}
//如果没有对应的值,入栈
else {
stack.push(ch);
}
}
return stack.isEmpty();
}
}
class Solution {
public int evalRPN(String[] tokens) {
Stack<Integer> stack = new Stack<Integer>();
for (int i = 0;i<tokens.length;i++){
//如果是数字,入栈
if (isNumber(tokens[i])){
stack.push(Integer.parseInt(tokens[i]));
}else {
int num1 = stack.pop();
int num2 = stack.pop();
switch (tokens[i]){
case "+": stack.push(num2+num1);break;
case "-": stack.push(num2-num1);break;
case "*": stack.push(num2*num1);break;
case "/": stack.push(num2/num1);break;
default:
}
}
}
return stack.peek();
}
public boolean isNumber(String token) {
return !(token.equals("*"))&&!(token.equals("+"))&&!(token.equals("-"))&&!(token.equals("/"));
}
}
class MyQueue {
//输入栈
private Stack<Integer> inStack;
//输出栈
private Stack<Integer> outStack;
/** Initialize your data structure here. */
public MyQueue() {
this.inStack=new Stack<Integer>();
this.outStack=new Stack<Integer>();
}
//入栈
public void push(int x) {
inStack.push(x);
}
//出栈
public int pop() {
//如果输出栈为空,则将输入栈全部弹出并压入输出栈栈中,然后outStack.pop()
if(outStack.isEmpty()){
while(!inStack.isEmpty()){
outStack.push(inStack.pop());
}
}
return outStack.pop();
}
//取得队头数据
public int peek() {
if(outStack.isEmpty()){
while(!inStack.isEmpty()){
outStack.push(inStack.pop());
}
}
return outStack.peek();
}
public boolean empty() {
return inStack.isEmpty() && outStack.isEmpty();
}
}
-用两个队列
class MyStack {
Queue<Integer> queue1;
Queue<Integer> queue2;
/** Initialize your data structure here. */
public MyStack() {
queue1 = new LinkedList<Integer>();
queue2 = new LinkedList<Integer>();
}
//入栈
public void push(int x) {
//当前新增元素后进队列
queue1.offer(x);
//老队列后进
while (!queue2.isEmpty()){
queue1.offer(queue2.poll());
}
//搞完后更新老队列
//其实此时的queue1已经是空队列了
Queue<Integer> tmp = queue1;
queue1 = queue2;
queue2 = tmp;
}
//出栈
public int pop() {
return queue2.poll();
}
public int top() {
return queue2.peek();
}
public boolean empty() {
return queue2.isEmpty();
}
}
-用1个队列
class MyStack {
Queue<Integer> queue;
/** Initialize your data structure here. */
public MyStack() {
queue = new LinkedList<Integer>();
}
/** Push element x onto stack. */
public void push(int x) {
int n = queue.size();
queue.offer(x);
for (int i = 0; i < n; i++) {
queue.offer(queue.poll());
}
}
/** Removes the element on top of the stack and returns that element. */
public int pop() {
return queue.poll();
}
/** Get the top element. */
public int top() {
return queue.peek();
}
/** Returns whether the stack is empty. */
public boolean empty() {
return queue.isEmpty();
}
}
通过以上几道题,反复去求解多种解法,栈和队列就基本掌握了