🍦栈 栈是一种数据结构,他是一种只允许在一端固定进行插入和删除操作的特殊线性表。先进入的数据被压入栈底,最后进入的数据被放在栈顶,需要读出的数据从栈顶开始弹出,按照先入后出的原则。
操作:
入栈:也称为压栈/进栈,将插入的元素放在栈顶;
出栈: 将栈顶的元素进行删除;
栈的方法
方法 | 功能 |
---|---|
Stack() | 构造一个空的栈 |
E push(E e) | 将元素入栈 |
E pop() | 将元素出栈 |
E peek() | 获取栈顶元素 |
int size() | 获取栈中有效个数大小 |
boolean empty() | 判断栈是否为空 |
细心的同学观察图片和表格中的方法会发现,图片中并没有size方法,是因为Stack继承于Vector,他使用的size方法是Vector中的方法;
什么是Vector?
什么是线程安全?
方法的使用:
public static void main(String[] args) {
Stack<Integer> stack=new Stack<>();
//入栈
stack.push(1);
stack.push(2);
stack.push(3);
//获取有效个数大小
System.out.println(stack.size());//3
//获取栈顶元素
System.out.println(stack.peek());//3
//出栈
stack.pop();
//获取栈顶元素
System.out.println(stack.peek());//2
//查找元素下标
System.out.println(stack.search(2));
}
//数组模拟实现栈
public class MyStack {
//元素
public int[] n;
//有效元素大小
public int usedsize;
//构造方法
public MyStack(int[] n) {
this.n = n;
}
//入栈:将元素进行插入
//1.判断是否满了,满了用Arrays.copyOf进行扩容
//1.用元素放入数组中,
//2.元素个数增加
public void push(int x){
if(isFull()){
this.n= Arrays.copyOf(n,2*n.length);
}
n[usedsize]=x;
usedsize++;
}
private boolean isFull(){
return usedsize==n.length;
}
//出栈:将栈顶元素拿出
//1.判断栈是否为空;
// 2.将栈中元素减减即可
public int pop(){
if(empty()){
return -1;
}
int val=n[usedsize-1];
usedsize--;
return val;
}
//获取栈顶元素
//1.判断栈是否为空,如果为空抛出异常
// 2.获取栈中元素
public int peek(){
if(empty()){
throw new EmptyStackException();
}
return n[usedsize-1];
}
//判断栈是否为空
//看其有效个数是否为0
public boolean empty()throws EmptyStackException{
return this.usedsize==0;
}
}
可以通过链表来模拟实现栈吗?
答案是:可以的;
1.如果采用单链表来实现:
2.如果采用双链表来实现:
🍦队列 队列就像日常生活中的排队一样,一端用于插入元素,称为队尾;另一端用于删除元素,称为队头。其遵循的的是先进先出的原则。
操作:
队列的分类
Queue是一个接口,不能实例化本身,但只要实现了这个接口都可以实例化,比如LinkedList、ArrayDeque以及PriorityQueue等等其他;
public static void main(String[] args) {
Queue<Integer> queue=new LinkedList<>();
Queue<Integer> queue1=new ArrayDeque<>();
Queue<Integer> queue2=new PriorityQueue<>();
}
看下面的图片,我们可以发现他们分为两类使用效果相同,但是使用目的不同:
方法 | 功能 |
---|---|
boolean offer(E e) | 入列队 |
E poll() | 出列队 |
peek() | 获取队头元素 |
int size() | 有效元素个数 |
boolean isEmpty() | 判断是否为空 |
public static void main(String[] args) {
Queue<Integer> queue=new LinkedList<>();
//入队
queue.offer(1);
queue.offer(2);
queue.offer(3);
//获取有效元素个数
System.out.println(queue.size());//3
//获取队头元素
System.out.println(queue.peek());//1
//出队
System.out.println(queue.poll());//1
}
普通队列用双链表模拟实现:
public class MyQueue {
//创建节点类
static class ListNode{
public int val;
public ListNode prev;
public ListNode next;
public ListNode(int val) {
this.val = val;
}
}
public ListNode first=null;
public ListNode last=null;
public int usedSize=0;
//入队
//判断是否为空,如果为空将头尾节点都等于该新节点
//如果不是,将节点添加到队尾
//有效元素个数增加
public void offer(int val){
ListNode listNode=new ListNode(val);
if(isEmpty()){
first=last=listNode;
}else{
last.next=listNode;
listNode.prev=last;
last=listNode;
}
usedSize++;
}
//出队
//判断队列是否为空;
//出队头元素,将队头指针向后移动
//使用元素个数减少
public int poll(){
if(isEmpty()){
return -1;
}
int val= first.val;
first=first.next;
if(first!=null){
first.prev=null;
}
return val;
}
//获取队头元素
//判断队列是否为空
//如果不为空,直接返回队头元素
public int peek(){
if(isEmpty()){
return -1;
}
return first.val;
}
//判断是否为空
//判断有效元素个数是否为0
public boolean isEmpty(){
return usedSize==0;
}
}