栈
概念
栈:一种特殊的线性表,其只允许在固定的一端进行插入和删除元素操作。进行数据插入和删除操作的一端称为栈顶,另一端称为栈底。栈中的数据元素遵守后进先出**LIFO(Last In First Out)**的原则。
压栈:栈的插入操作叫做进栈/压栈/入栈,入数据在栈顶。
出栈:栈的删除操作叫做出栈。出数据在栈顶。
实现
可以利用顺序表实现,也可以用链表实现
顺序表实现:
public class MyStack {
public int[] elem;
public int usedSize;//top
public MyStack() {
this.elem = new int[5];
}
//入栈
public void push(int item) {
if(isFull()) {
return;
}
elem[usedSize++] = item;
}
//出栈
public int pop() {
if(isEmpty()) {
return -1;
}
return elem[--usedSize];
}
//查看栈顶元素
public int peek(){
if(isEmpty()) {
return -1;
}
return elem[usedSize - 1];
}
//判断栈空
public boolean isEmpty() {
if(usedSize == 0) {
return true;
}
return false;
}
//判断栈满
public boolean isFull() {
if(usedSize == 5) {
return true;
}
return false;
}
}
队列
概念
队列:只允许在一端进行插入数据操作,在另一端进行删除数据操作的特殊线性表,队列具有先进先出FIFO(First In First Out) 入队列:进行插入操作的一端称为队尾(Tail/Rear) 出队列:进行删除操作的一端称为队头(Head/Front)
实现
队列也可以数组和链表实现,使用链表的结构更好一些
class Node {
public int val;
public Node next;
public Node(int val) {
this.val = val;
}
}
public class MyQueue {
public Node head;
public Node tail;
//入队列
public void offer(int val) {
Node node = new Node(val);
if(head == null) {
head = node;
tail = node;
return;
}
tail.next = node;
tail = tail.next;
}
//出队列
public int poll() {
if(head == null) {
throw new RuntimeException();
}
Node tmp = head;
if(head.next == null) {
head = null;
tail = null;
}else {
head = head.next;
}
return tmp.val;
}
//查看队列头元素
public int peek() {
if(head == null) {
throw new RuntimeException();
}
return head.val;
}
//队列判空
public boolean isEmpty() {
return head == null;
}
}
循环队列
循环队列通常由数组实现
public class MyCircularQueue {
public int[] elem;
public int front;
public int rear;
public MyCircularQueue(int k) {
this.elem = new int[k];
}
//入循环队列
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;
}
if(rear == 0) {
return elem[elem.length - 1];
}
return elem[(rear - 1)];
}
//判断循环队列为空
public boolean isEmpty() {
return front == rear;
}
//判断循环队列为满
public boolean isFull() {
return (rear + 1) % elem.length == front;
}
}
注意队列为空和队列为满的条件。
双端队列(deque)
双端队列是指允许两端都可以进行入队和出队操作的队列。
双端循环队列
public class MyCircularDeque {
public int[] elem;
public int front;
public int rear;
public int size;
public MyCircularDeque(int k) {
size = k + 1;
this.elem = new int[size];
front = 0;
rear = 0;
}
public boolean insertFront(int value) {
if(isFull()) {
return false;
}
front = (front - 1 + size) % size;
elem[front] = value;
return true;
}
public boolean insertLast(int value) {
if(isFull()) {
return false;
}
elem[rear] = value;
rear = (rear + 1 + size) % size;
return true;
}
public boolean deleteFront() {
if(isEmpty()) {
return false;
}
front = (front + 1 + size) % size;
return true;
}
public boolean deleteLast() {
if(isEmpty()) {
return false;
}
rear = (rear - 1 + size) % size;
return true;
}
public int getFront() {
if(isEmpty()) {
return -1;
}
return elem[front];
}
public int getRear() {
if(isEmpty()) {
return -1;
}
return elem[(rear - 1 + size) % size];
}
public boolean isEmpty() {
return front == rear;
}
public boolean isFull() {
return (rear + 1 + size) % size == front;
}
}
栈的常用方法和队列中一些方法的比较
Stack
方法 | 解释 |
---|---|
E push(E item) | 压栈 |
E pop() | 出栈 |
E peek() | 查看栈顶元素 |
boolean empty() | 判断栈是否为空 |
Queue
抛出异常 | 返回特殊值 | |
---|---|---|
入队列 | add(e) | offer(e) |
出队列 | remove() | poll() |
查看队首元素 | element() | peek() |
Queue
抛出异常 | 返回特殊值 | 抛出异常 | 返回特殊值 | |
---|---|---|---|---|
入队列 | addFirst(e) | offerFirst(e) | addLast(e) | offerLas(e) |
出队列 | removeFirst() | pollFirst() | removeLas(e) | pollLas(e) |
查看元素 | getFirst() | peekFirst() | getLas(e) | peekLas(e) |
一般使用返回特殊值的方法。