栈
概念
只能在表的一端进行插入和删除运算的线性表
进行插入和删除运算的一端叫栈顶,另一端叫栈底
栈中的数据按照先进后出(FILO)或后进先出(LIFO)的原则
进栈:在栈顶插入数据,叫做入栈/进栈/压栈。
出栈:在栈顶删除数据,叫做出栈。
栈的基本操作:建栈,入栈,出栈,读栈顶元素,判断栈空,栈满等
栈的顺序存储
栈空时 usedSize == 0
栈满时 usedSize == elem.length
public class MyStack {
public int[] elem;
public int usedSize;
public MyStack() {
this.elem = new int[10];
}
//压栈
public void push(int val) {
if (isFull()) {
//扩容 2倍
elem = Arrays.copyOf(elem,2*elem.length);
}
elem[usedSize++] = val;
}
//判断是否满了
public boolean isFull() {
return usedSize == elem.length;
}
//出栈
public int pop() {
if(isEmpty()) {
throw new EmptyException("栈是空的!");
}
return elem[--usedSize];
}
//判断是否为空
public boolean isEmpty() {
return usedSize == 0;
}
//查看栈顶元素
public int peek() {
if(isEmpty()) {
throw new EmptyException("栈是空的!");
}
return elem[usedSize - 1];
}
}
public class EmptyException extends RuntimeException{
public EmptyException(String message) {
super(message);
}
}
栈的链式存储
head 结点为null时 栈空
public class MyStack1 {
// 结点
static class Node {
public int val;
public Node next;
public Node(int val) {
this.val = val;
}
}
public Node head;
public int usedSize;
//压栈
public void push(int val) {
Node node = new Node(val);
if (head == null) {
head = node;
} else {
node.next = head;
head = node;
}
usedSize++;
}
//出栈
public int pop() {
if(isEmpty()) {
throw new EmptyException("栈是空的!");
}
int ret = head.val;
head = head.next;
usedSize--;
return ret;
}
//判断是否为空
public boolean isEmpty() {
return usedSize == 0;
}
//查看栈顶元素
public int peek() {
if(isEmpty()) {
throw new EmptyException("栈是空的!");
}
return head.val;
}
}
队列
概念
队列是一种先进先出(FIFO)的线性表.
它只允许在表的一端进行插入(队尾)
而在另一端删除元素 (队头)
循环队列
用一个数组来实现队列, front表示队头下标,rear表示队尾下标
初始状态是front=rear=0
入队时rear+1
出队时front+1
出队后front+1,front前面的空间就不能用了,会导致假溢出
下图中,还有一个空间,但是不能再入队了
所以就提出了循环队列,让下标循环起来
牺牲一个空间来区分队列空和队列满
// 循环队列
public class MyCircularQueue {
private int[] elem;
private int front;
private int rear;
public MyCircularQueue(int k) {
elem = new int[k + 1];
}
// 入队
public boolean enQueue(int value) {
if (isFull()) {
return false;
}
elem[rear] = value;
rear = (rear + 1) % elem.length;
return true;
}
// 出队
public boolean deQueue() {
if (isEmpty()) {
return false;
}
front = (front + 1) % elem.length;
return true;
}
// 获取队首元素
public int Front() {
if (isEmpty()) {
return -1;
}
return elem[front];
}
// 获取队尾元素
public int Rear() {
if (isEmpty()) {
return -1;
}
return elem[(rear - 1 + elem.length) % elem.length];
}
// 是否为空
public boolean isEmpty() {
return front == rear;
}
// 是否已满
public boolean isFull() {
//浪费一个空间来区分 队列空 和 队列满
return (rear + 1) % elem.length == front;
}
}
链队列
public class MyQueue {
static class Node {
public int val;
public Node next;
public Node(int val) {
this.val = val;
}
}
public Node head;
public Node last;
public int usedSize;
//入队
public void offer(int val) {
Node node = new Node(val);
if (head == null) {
head = node;
last = node;
} else {
last.next = node;
last = node;
}
usedSize++;
}
//出队
public int poll() {
if(empty()) {
throw new EmptyException("队列为空");
}
int ret = head.val;
head = head.next;
if (head == null) {
//只有一个结点,出队后就没了,last也置空
last = null;
}
usedSize--;
return ret;
}
// 是否为空
public boolean empty() {
return usedSize == 0;
}
// 查看队首
public int peek() {
if(empty()) {
throw new EmptyException("队列为空");
}
return head.val;
}
//大小
public int size() {
return usedSize;
}
public void clear() {
head = null;
last = null;
}
}