数据结构Java--4

前言

上一篇博客没有对LinkedList进行太多的讲解,本博客会在队列的内容进行详细的说明,此外本系列博客不会进行刷题网站的题目讲解,主要目的是介绍说明基本的数据结构的概念。

栈的特性

栈(stack)是一种新的数据结构,它遵循先进后出的原则。什么意思呢?拿生活中的事物来举例

图片来源互联网侵删

我们在打开羽毛球桶的时候,假设里面没有羽毛球,我们要往里面放球,比如放了三个球,第一个球即为球1,第二个为球2,第三个为球3。在装完之后,我们想要取到球1是不是要先把,压在球1上面的球2球3拿出来才能拿到球1。

我们要说的栈就是像这样的结构,一种先进后出的结构。

栈的模拟实现

栈的模拟可以有多种形式,可以由数组进行实现,也可以由我们上一篇说过的链表来实现,甚至可以用队列来实现。这里我们使用数组来实现。

栈主要涉及三个方法,push(加入数据),pop(弹出数据),peek(查看栈顶数据)

也都很好理解根据翻译意思,push是推的意思自然要把元素推栈的底部,pop有爆开脱落弹走的意思所以就是弹出数据,peek如果有玩过CounterStrike(反恐精英)的朋友应该很熟悉,意思就是偷瞄一眼再回来的意思,在这里的意思就是看一下栈顶数据是什么,但是不做出改动。

public class MyStack {
    private int[] elem;
    private int usedSize;
    private static final int DEFAULT_SIZE = 10;
    public MyStack(){
        elem = new int[DEFAULT_SIZE];
    }

    public void push(int val){
        if(isFull()){
            elem = Arrays.copyOf(elem,2*elem.length);
        }

        elem[usedSize] = val;
        usedSize++;
    }

    private boolean isFull(){
        return usedSize==elem.length;
    }

    public int pop(){
        if(isEmpty()){
            return -1;
        }
        int data = elem[usedSize-1];
        usedSize--;
        return data;
    }

    private boolean isEmpty(){
        return usedSize == 0;
    }

    public int peek(){
        if(isEmpty()){
            return -1;
        }
        int data = elem[usedSize-1];
        return data;
    }

    public int size(){
        return usedSize;
    }

}

 需要注意的是usedSize和数组的容量大小,确保没有越界

栈的使用

实例化一个栈的格式为:Stack<T> stack = new Stack<>(); T是任意包装类型。

public class UseStack {
    public static void main(String[] args) {
        Stack<Integer> stack = new Stack<>();
        stack.push(1);
        stack.push(2);
        stack.push(3);
        stack.push(4);
        System.out.println(stack.pop());
        System.out.println(stack.pop());
        System.out.println(stack.peek());
        System.out.println(stack.peek());
    }
}

这里我们打个断点进行debug

结果和用法都和前面模拟的一样,有个小细节,Stack自带的pop和peek方法都是带有返回值的,所以可以直接用数据进行接收并直接打印输出。

队列

队列和LinkedList的关系,集合框架图(部分)

在具体说队列的特性之前,我先解决上一篇博客留下的问题。

直线之间没有交点

我们都知道,不可以直接实例化一个接口,只能实例化一个他派生出来的类,然后发生向上转型。这张图里的关系就解释了为什么我们更推荐以List-ArrayList 和 List-LinkedList的方式去书写。

当然也不防Queue-ArrayList或者List-Stack这样的奇葩写法,这类写法虽然语法上没有出错误,但是不推荐这样写,具体为什么不推荐这样写,现阶段的知识还不能解释其中的原因,后面深入学习之后会知道为什么,这里点到为止。

队列的特性

队列(queue) 是一种先进先出的数据结构,什么叫先进先出。就像现实中的排队一样,先来后到,先排队的人肯定先进。

 队列模拟实现

前面了解了队列的特性,我们可以发现队列是一种容器两头都发生变化的结构,所以我们不考虑使用数组,因为数组比较适合静态单向的输入输出数据,如果要使用数组的话,要更加的麻烦。这里我们使用链表来进行模拟,链表并不是固定大小的容器,而且头尾分明,更加符合队列的结构。

链表方面我们采用双向链表

队列主要围绕offer,poll,peek几个方法,offer提供数据,入队。poll放出数据,出队。peek和前面栈一样,查看出队口的数据。

public class MyQueue {
//头进尾出
    static class ListNode {
        private int val;
        private ListNode next;
        private ListNode prev;
        public ListNode(int val) {
            this.val = val;
        }
    }

    private ListNode front;
    private ListNode rear;
    private int usedSize;

    public void offer(int val) {
        ListNode node = new ListNode(val);
        if(front==null) {
            front=rear=node;
        }else {
            node.next = front;
            front.prev = node;
            front = node;
        }
        usedSize++;
    }

    public int poll() {
        if(rear==null) {
            return -1;
        }
        int data = rear.val;
        if(rear==front) {
            rear = null;
            front = null;
        }
        rear = rear.prev;
        rear.next = null;
        usedSize--;
        return data;
    }

    public int peek() {
        int data = rear.val;
        return data;
    }

    public int size() {
        return usedSize;
    }

    public boolean isEmpty() {
        return usedSize==0;
    }

}

push和poll方法需要注意队列为空的情况即可,其余难度不高,这里一笔带过。

队列的使用

队列实例化的格式为Queue<> queue = new LinkedList<>();

这里需要注意是new一个LinkedList而不是Queue,因为Queue是一个接口,不是一个类,前面集合框架图也有说明。

public class UseQueue {
    public static void main(String[] args) {
        Queue<Integer> queue = new LinkedList<>();
        queue.offer(1);
        queue.offer(2);
        queue.offer(3);
        queue.offer(4);
        queue.offer(5);
        System.out.println(queue.poll());
        System.out.println(queue.poll());
        System.out.println(queue.peek());
        System.out.println(queue.peek());
    }
}

 双端队列

双端队列Deque是一种两头都可以进行入队出队的结构,现阶段只做浅了解。

public class UseDeque {
    public static void main(String[] args) {
        Deque<Integer> stack = new ArrayDeque<>();//双端队列的线性实现
        Deque<Integer> queue = new LinkedList<>();//双端队列的链式实现
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值