栈(Stack)
1.1 概念
栈:一种特殊的线性表,其只允许在固定的一端进行插入和删除元素操作。进行数据插入和删除操作的一端称为栈 顶,另一端称为栈底。
压栈:栈的插入操作叫做进栈/压栈/入栈,入数据在栈顶。
出栈:栈的删除操作叫做出栈。出数据在栈顶
1.2 实现
1.基于顺序表实现
class MyStack {
public int[] arr = new int[100];
//[0,size)
public int size = 0;
//头插
public void push(int val) {
arr[size] = val;
size++;
}
//头删
public Integer pop() {
if(size <= 0) {
return null;
}
int ret = arr[size-1];
size--;
return ret;
}
//
public Integer peek() {
if(size <= 0) {
return null;
}
int ret = arr[size-1];
return ret;
}
}
public class Main {
public static void main(String[] args) {
MyStack myStack = new MyStack();
myStack.push(1);
myStack.push(2);
myStack.push(3);
myStack.push(4);
while (true) {
Integer cur = myStack.pop();
if(cur == null) {
break;
}
System.out.println(cur);
}
}
}
2.基于链表实现
public class MyStack {
static class Node {
public int val;
public Node next;
public Node(int val) {
this.val = val;
}
}
Node head = new Node(-1);
//头插
public void push(int val) {
Node newNode = new Node(val);
newNode.next = head.next;
head.next = newNode;
}
//头删
public Integer pop() {
Node toDel = head.next;
if(toDel == null) {
return null;
}
head.next = toDel.next;
return toDel.val;
}
//取首元素
public Integer peek() {
if(head.next == null) {
return null;
}
return head.val;
}
}
public class Main {
public static void main(String[] args) {
MyStack myStack = new MyStack();
myStack.push(5);
myStack.push(6);
myStack.push(7);
myStack.push(8);
while (true) {
Integer cur = myStack.pop();
if(cur == null) {
break;
}
System.out.println(cur);
}
}
}
库中的栈的操作
方法 | 解释 |
---|---|
E push(E item) | 压栈 |
E pop() | 出栈 |
E peek() | 查看栈顶元素 |
boolean empty() | 判断栈是否为空 |
队列(Queue)
2.1 概念
队列:只允许在一端进行插入数据操作,在另一端进行删除数据操作的特殊线性表.
入队列:进行插入操作的一端称为队尾
出队列:进行删除操作的一端称为队头
2.2 实现
1.基于顺序表实现
public class MyQueue {
private int[] arr = new int[100];
private int head = 0;//头
private int tail = 0;//尾
private int size = 0;//元素个数
//入队列
public boolean offer(int val) {
//返回boolean判断失败成功
if(size == arr.length) {
return false;
}
arr[tail] = val;
tail++;
if(tail >= arr.length) {
tail = 0;
}//tail %= arr.length;
size++;
return true;
}
//出队列
public Integer poll() {
if(size == 0) {
return null;
}
int ret = arr[head];
head++;
if(head >= arr.length) {
head = 0;
}
size--;
return ret;
}
//取队首元素
public Integer peek() {
if(size == 0) {
return null;
}
return arr[head];
}
}
public class Main {
public static void main(String[] args) {
MyQueue myQueue = new MyQueue();
myQueue.offer(5);
myQueue.offer(6);
myQueue.offer(7);
myQueue.offer(8);
while (true) {
Integer cur = myQueue.poll();
if(cur == null) {
break;
}
System.out.println(cur);
}
}
}
2.基于链表实现
public class MyQueue {
static class Node {
public int val;
public Node next;
public Node(int val) {
this.val = val;
}
}
private Node head = new Node(-1);
private Node tail = head;
private int size;//元素个数
//入队列
public void offer(int val) {
Node newNode = new Node(val);
tail.next = newNode;
tail=tail.next;
}
//出队列
public Integer poll() {
if(head.next == null) {
return null;
}
Node toDel = head.next;
head.next = toDel.next;
if(head.next == null) {
tail = head;
}
return toDel.val;
}
//取队首元素
public Integer peek() {
if(head.next == null) {
return null;
}
return head.next.val;
}
}
public class Main {
public static void main(String[] args) {
MyQueue myQueue = new MyQueue();
myQueue.offer(1);
myQueue.offer(2);
myQueue.offer(3);
myQueue.offer(4);
while (true) {
Integer cur = myQueue.poll();
if(cur == null) {
break;
}
System.out.println(cur);
}
}
}
注意
队列变种:
* 1.普通队列:先进先出
* 2.消息队列:按照"(业务)类型"获取元素
* 3.优先队列:按照优先级获取优先级最高的元素
* 4.阻塞队列:队列空–出队阻塞;队列满–入队阻塞
* 阻塞:代码执行到某个地方就不往下走了,一直等待
* 5.无锁队列:线程安全,比较高效(不是通过锁实现线程安全,通过CAS操作实现);
* 6.双端队列:允许两端都可以进行入队和出队操作的队列,
* 链表队列--插入元素无上限---效率低(操作引用)
* 数组队列--插入元素有上限---效率高(操作值)
库中的队列的操作
1.普通队列
错误处理 | 抛出异常 | 返回特殊值 |
---|---|---|
入队列 | add(e) | offer(e) |
出队列 | remove() | poll() |
队首元素 | element() | peek() |
2.双端队列
区别
栈 | 队列 |
---|---|
入栈:元素从栈顶向下 | 入队列:元素从队尾插入 |
出栈:删除栈顶元素 | 出队列:删除队首元素 |
取栈顶元素:获取最上面元素 | 取队首元素:获取队首位置元素 |
后进先出 | 先进先出 |