1、栈
1.1 概念
栈是一种特殊的线性表,只能在固定的一端插入或删除元素,插入或删除元素的一端称为栈顶,另一端称为栈底。
特点:先入后出,后入先出。
1.2 栈的基本操作
1.3 栈的模拟实现
使用线性表来模拟实现 定义数组elem来存放元素,usersize表示元素的个数,入栈 usersize++;出栈usersize--;判断栈是否为空 usersize == 0
import java.util.Arrays; public class MyStack { public int[] elem; public int usersize; public static final int DEFAULT_CAPACITY = 10; public MyStack(){ elem = new int[DEFAULT_CAPACITY]; } public void push(int val){ if(isFull()){ this.elem = Arrays.copyOf(elem,2*elem.length); } elem[usersize++] = val; } public boolean isFull(){ return usersize == elem.length; } public int pop(){ if(empty()){ throw new EmptyRunException("栈为空,无法获取栈顶元素"); } int tmp = elem[usersize - 1]; usersize--; return tmp; } public int peek(){ if(empty()){ throw new EmptyRunException("栈为空,无法获取栈顶元素"); } return elem[usersize-1]; } public int size(){ return usersize; } public boolean empty(){ return 0 == usersize; } }
栈的简单使用
public class Test{
public static void main(String[] args) {
Stack<Integer> s = new Stack();
s.push(1);
s.push(2);
s.push(3);
s.push(4);
System.out.println(s.size()); // 获取栈中有效元素个数---> 4
System.out.println(s.peek()); // 获取栈顶元素---> 4
s.pop(); // 4出栈,栈中剩余1 2 3,栈顶元素为3
System.out.println(s.pop()); // 3出栈,栈中剩余1 2 栈顶元素为3
if(s.empty()){
System.out.println("栈空");
} else {
System.out.println(s.size());
}
}
}
栈、虚拟机栈、栈帧有什么区别呢?
(1)栈:一般认为是后进先出的一种数据结构——在java的集合中有对应的实现---Stack,
Stack在实现时继承了Vector。
栈的定义
栈是一种特殊的线性表,只能在固定的一端插入或删除元素,插入或删除元素的一端称为栈顶,另一端称为栈底。栈顶:线性表允许进行插入删除的那一端。
栈底:固定的,不允许进行插入和删除的另一端。
空栈:不含任何元素的空表。(2)Java虚拟机栈(Java Virtual Machine Stack),早期也叫Java栈。每个线程在创建时都会创建一个虚拟机栈,其内部保存一个个的栈帧(Stack Frame),对应着一次次的Java方法调用,是线程私有的。生命周期和线程一致,作用:主管Java程序的运行,它保存方法的局部变量、部分结果,并参与方法的调用和返回。栈的特点:栈是一种快速有效的分配存储方式,访问速度仅次于程序计数器。JVM直接对Java栈的操作只有两个:1、每个方法执行,伴随着进栈(入栈、压栈);2、执行结束后的出栈工作。对于栈来说不存在垃圾回收(但栈存在溢出的情况)方法结束,栈回收
(3)栈帧也叫过程活动记录,是编译器用来实现过程/函数调用的一种数据结构。简言之,栈帧就是利用
EBP
(栈帧指针,请注意不是ESP)寄存器访问局部变量、参数、函数返回地址等的手段。
2、队列
2.1 概念
2.2 队列的基本操作
2.3 队列的模拟实现
采用链式结构来实现, 双向链表 尾插表示入队,头删表示出队
public class Myqueue {
public static class ListNode{
public int val;
public ListNode prev;
public ListNode next;
public ListNode(int val) {
this.val = val;
}
}
ListNode head;//队头
ListNode last;//队尾
public void offer(int val) {
ListNode node = new ListNode(val);
if(head == null){
head = last = node;
} else {
last.next = node;
node.prev = last;
last = node;
}
}
public int poll(){
if(head == null) {
return -1;
}
int val = -1;
if(head.next == null) {
val = head.val;
head = null;
last = null;
return val;
}
val = head.val;
head = head.next;
head.prev = null;
return val;
}
public boolean ifEmpty(){
return head == null;
}
public int peek () {
if(head == null) {
return -1;
}
return head.val;
}
}
3、循环队列
1. 通过添加 size 属性记录2. 保留一个位置 判断满的条件 (rear + 1) % elem.length == front3. 使用标记
class MyCircularQueue {
int[] elem;
int front;
int rear;
public MyCircularQueue(int k) {
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;
}
int index = (rear == 0) ? elem.length-1 : rear-1;
return elem[index];
}
public boolean isEmpty() {
return front == rear;
}
public boolean isFull() {
return (rear + 1) % elem.length == front;
}
}