Java:自己实现栈和队列

目录

            一、什么是栈,什么是队列?

            二、自己实现栈

            三、自己实现队

            四、标准库中的栈和队


一、什么是栈,什么是队列?

栈:栈的特点是后进先出,也就是从哪边进从哪边出(就像装在罐子里的糖果,最后装进去的,最先被取出来)

队列:队的特点是先进先出,也就是从哪边进,从另一边出(就像我们排队买饭一样,先排队的人先买到饭)

二、自己实现栈

2.1 核心操作

  • 入栈push(把元素放到栈里面)
  • 出栈pop(把最后进来的元素删掉)
  • 取栈顶元素peek(获取到最后一个进来的元素的结果)

2.2 使用顺序表实现

尾插尾删即可(不建议头插头删,由于顺序表是基于数组实现的,如果头插头删,可能会存在大量的挪动元素,效率较低)

public class MyStack1 {
    private int[] data=new int[100];
    private int size=0;
    //入栈
    public void push(int val){
        if(size>=data.length){
            return;
        }
        data[size]=val;
        size++;
    }
    //出栈
    public Integer pop(){
        if(size==0){
            return null;
        }
        int ret=data[size-1];
        size--;
        return ret;
    }

    //取栈顶元素
    public Integer peek(){
        if(size==0){
            return null;
        }
        return data[size-1];
    }
}

2.3 使用链表实现

头插头删即可(也可以尾插尾删,要记录链表尾节点,所以会额外记录一些数据,代码稍微复杂一点)

public class MyStack2 {
    //静态内部类Node,使这个类不依附于MyStack这个类
    static class Node{
        int val;
        Node next;
        public Node(int val) {
            this.val = val;
        }
    }
    private Node head=null;
    //入栈
    public void push(int val){
        Node newNode=new Node(val);
        if(head==null){
            head=newNode;
            return;
        }
        newNode.next=head;
        head=newNode;
    }
    //出栈
    public Integer pop(){
        if(head==null){
            return null;
        }
        int ret=head.val;
        head=head.next;
        return ret;
    }

    //取栈顶元素
    public Integer peek(){
        if(head==null){
            return null;
        }
        return head.val;
    }

}

三、自己实现队

3.1 核心操作

  • 入队offer
  • 出队poll
  • 取队首元素peek

3.2 使用顺序表实现(环形队列)

尾插头删即可。现在来思考一下,假如我们的队列中存满了,接着出队了几个元素,意味着又多了几个空间,此时再想入队,我们该如何利用这几个空间呢?如何判断队列真正的满了呢?

我们可以定义一个head引用记录队首的位置,定义tail记录队尾的位置,定义一个size记录队中当前元素的个数。当size>=数组的长度时,我们就认为队满了,和tail是否走到数组的最后一个位置无关,因为也可能有因为出队,还有空间没使用的情况。

 

如果tail已经走到了数组的末尾,但是队并没有满,那么将tail置0即可。

public class MyQueue1 {
    private int[] data=new int[100];
    private int head=0;
    private int tail=0;
    private int size=0;
    //入队
    public boolean offer(int val){
        if(size==data.length){
            return false;
        }
        data[tail]=val;
        tail++;
        size++;
        if(tail==data.length){
            tail=0;
        }
        return true;
    }
    //出队
    public Integer poll(){
        if(size==0){
            return null;
        }
        int ret=data[head];
        head++;
        size--;
        if(head==data.length){
            head=0;
        }
        return ret;
    }
    //取队首元素
    public Integer peek(){
        if(size==0){
            return null;
        }
        return data[head];
    }
}

3.3 使用链表实现

尾插头删即可,记录链表的头节点和尾节点。

public class MyQueue2 {
    static class Node{
        int val;
        Node next;
        public Node(int val) {
            this.val = val;
        }
    }
    private Node head=null;
    private Node tail=null;
    //入队
    public void offer(int val){
        Node newNode=new Node(val);
        if(head==null){
            head=newNode;
            tail=newNode;
            return;
        }
        tail.next=newNode;
        tail=tail.next;
    }
    //出队
    public Integer poll(){
        if(head==null){
            return null;
        }
        int ret=head.val;
        head=head.next;
        return ret;
    }
    //取队首元素
    public Integer peek(){
        if(head==null){
            return null;
        }
        return head.val;
    }
}

四、标准库中的栈和队

4.1 分析上图

上面的图中,我们可以看到,Stack是一个类,也就意味着可以直接拿过来用,而Queue是一个接口,不能实例化,需要创建相应的子类,Java标准库中提供的Queue对应的实现只有LinkedList用链表实现这一种选择,没有提供环形队列这个版本。

注意:由于Stack继承自Vector,实现了List接口,所以List能用的方法,在Stack中也都能用,但是我们还是尽量使用栈的核心操作:push,pop,peek

4.2 什么是Vector

Vector也是顺序表,和ArrayList差不多,细节上也有一些区别:

  • Vector线程安全,ArrayList线程不安全
  • 扩容策略不同
  • 出现的时机不同,Vector出现的早,ArrayList是后来才出现的。

4.3 标准库中的栈和队的方法

 

 

 

 

 

 

 

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值