数据结构--------队列(链表,数组实现)

1 队列

1 概念

  1. 队列是一种基于先进先出(FIFO)的数据结构,是一种只能在一端进行插入,在另一端进行删除操作的特殊线性表,它按照先进先出的原则存储数据,先进入的数据,在读取数据时先读被读出来。
  2. 图解:
    在这里插入图片描述

2 代码实现(链表)

  1. 原理:
    head为头节点,last指向最后一个节点,每次进行尾插法即插到last的后面,这样子就可以保证先进先出原则。

  2. 图解:
    在这里插入图片描述

  3. 代码:

    import java.util.Iterator;
    
    /**
     * @author JIN
     * @description 队列
     * @createTime 2020-08-17 08:15
     **/
    public class Queue<T> implements Iterable<T> {
        //头节点
        private Node head;
        //指向最后一个节点
        private Node last;
        //记录最后一个节点
        private int N;
    
        public Queue() {
            this.head = new Node(null, null);
            this.N = 0;
            this.last = null;
        }
    
        public boolean isEmpty() {
            return N == 0;
        }
    
        public int size() {
            return N;
        }
    
        public void add(T t) {
            //插入 分两种情况
            //第一种 队列本身为空,需要给头节点的next赋值
            //第二种 队列不为空,因此只需要在最后节点上插入
            if (head.next == null) {
                head.next = last = new Node(t, null);
            } else {
                last = last.next = new Node(t, null);
            }
            N++;
        }
    
        public T get() {
            //判断队列本身是否为空,若是,直接返回null
            if (isEmpty()) {
                return null;
            }
            T temp = head.next.data;
            head.next = head.next.next;
            N--;
            return temp;
        }
    
        //节点类
        class Node {
            private T data;
            private Node next;
    
            public Node(T data, Node next) {
                this.data = data;
                this.next = next;
            }
        }
        //下面的代码只是为了实现 foreach遍历 不重要
        @Override
        public Iterator<T> iterator() {
            return new Iterator<T>() {
                private Node n = head;
    
                @Override
                public boolean hasNext() {
                    return n.next != null;
                }
    
                @Override
                public T next() {
                    n = n.next;
                    return n.data;
                }
            };
        }
    
        public static void main(String[] args) {
            Queue<String> queue = new Queue<>();
            queue.add("a");
            queue.add("b");
            queue.add("c");
            queue.add("d");
            for (String s : queue) {
                System.out.println(s);
            }
            System.out.println("-----------");
            System.out.println(queue.get());
            System.out.println(queue.size());
        }
    }
    
    

3 代码实现(数组)

  1. 图解:
    在这里插入图片描述
    在这里插入图片描述

  2. 代码实现

    import java.util.Iterator;
    
    /**
     * @author JIN
     * @description 数组实现 队列
     * @createTime 2020-08-17 08:52
     **/
    public class Queue2<T> implements Iterable<T>{
        //数组用于存储数据
        private T[] data;
    
        //记录实际存储的个数
        private int N;
    
        //记录数组的容量
        private int capacity;
    
        //指向队列头,用于记录那个数组先出列
        private int front;
    
        //指向队列尾部,用于记录加入数据放在哪里
        private int rear;
    
        public Queue2(){
            this(8);
        }
    
        public Queue2(int size){
            //因为泛型没办法直接创建数组,即 new T[],是不可以通过的,
            //因此需要先创建Object数组 再强转
            this.data = (T[]) new Object[size];
            this.N = 0;
            this.front = 0;
            this.rear = 0;
            this.capacity = size;
        }
    
        public boolean isEmpty(){
            return N == 0;
        }
    
        public int size(){
            return N;
        }
    
        public int getCapacity(){
            return capacity;
        }
    
        //判断数组是否满了。
        public boolean isFull(){
            return (rear + 1) % capacity == front;
        }
    
        public void add(T t){
            //若满了,进行扩容
            if(isFull()){
                int newCapacity = capacity << 1;
                resize(newCapacity);
                capacity = newCapacity;
            }
            data[rear] = t;
            rear = (rear + 1) % capacity;
            N++;
        }
    
        public T get(){
            if(rear == front){
                return null;
            }
            N--;
            T value =  data[front];
            front = (front + 1) % capacity;
            return value;
        }
        //扩容的思想很简单,创建一个容量是用来数组容量的2倍的新数组
        //将旧数组的值 copy到新数组需要调整位置,
        //因为我们是环,具体在下面有个图说明。
        public void resize(int size){
            T[] olddata = data;
            this.data = (T[]) new Object[size];
            int temp = front;
            int index = 0;
            while((temp % capacity) != rear){
                data[index++] = olddata[temp];
                temp = (temp + 1) % capacity;
            }
            front = 0;
            rear = index;
        }
    
        @Override
        public Iterator<T> iterator() {
            return new Iterator<T>() {
                private int n = front;
                @Override
                public boolean hasNext() {
                    return n % capacity != rear;
                }
    
                @Override
                public T next() {
                    T value = data[n];
                    n = (n + 1) % capacity;
                    return value;
                }
            };
        }
    
        public static void main(String[] args) {
            Queue2<String> queue2 = new Queue2<>(5);
            queue2.add("a");
            queue2.add("b");
            queue2.add("c");
            queue2.add("d");
            System.out.println(queue2.get());
            System.out.println(queue2.get());
            queue2.add("e");
            queue2.add("f");
            queue2.add("g");
            queue2.add("h");
            queue2.add("i");
            queue2.add("j");
            System.out.println("-------------");
            //System.out.println(queue2.get());
            System.out.println("----------");
            for(String s : queue2){
                System.out.println(s);
            }
        }
    }
    
    
  3. 图解说明扩容方法:

    1. 若只是简单的复制,则会出现下面的情况,此时我需要再加入一个元素,注意,此时的maxcapacity是8,(rear + 1) % maxcapacity = 3 ,front 也为3,无法插入数据,此外,如果我们不插入数据,但是我们读数据呢,先读出a,(front + 1)%maxcapacity = 4,那读出来的是null,跟我们实际不符合,因此我们需要调整。
      在这里插入图片描述
    2. 在这里插入图片描述
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值