• 我们在算法2中已经使用Node实现了链表的功能。此时,我们进一步对链表进行延伸。题目:“使用单链表实现队列,实现后进先出的功能”。
  • 解题思路: 既然是链表,那么必然有一个头节点和尾结点。先进先出,那就是从头节点取数据,从尾节点添加数据
  • package code.code_02;
    
    /**
     * 使用单链表设计出队列
     */
    public class SingleNodeQueue<V> {
    
        private Node<V> head; //当前队列的头
        private Node<V> tail;   //当前队列的尾
        private int size;
    
        public SingleNodeQueue () {
            head = null;
            tail = null;
            size = 0;
        }
        //用于单链表的节点
        private class Node<V> {
            public V data;
            public Node<V> next;
    
            Node (V _data){
                this.data = _data;
            }
            public V getData() {
                return data;
            }
        }
    
        public boolean isEmpty () {
            return size == 0 ? true : false;
        }
    
        public int size () {
            return size;
        }
    
        //获取链表的头
        public V peek ()
        {
            Node<V> node = null;
            Node<V> next = null;
            if (head == null) {
                System.out.println("当前队列还没有设置元素");
                tail = null;
                return null;
            }
            else {
                //提前记录下头节点和头节点的持有的下一个节点的引用
                node = head;
                next = head.next;
                //将头节持有的下一个节点引用释放掉
                head.next = null;
                //因为头节点的下一个节点之前被记录过
                //此时,头节点head会释放掉原始的内存对象
                // 并且来到新的头节点位置(也就是之前的第二个节点)
                head = next;
                size--;
            }
            //因为node是局部变量,方法调用完成以后,node所对应的内存对象会被回收
            return node.getData();
        }
    
        //获取链表的头, 此方法是对peek进行的优化
        public V peek1 ()
        {
            V value = null;
            if (head == null) {
                System.out.println("当前队列还没有设置元素");
                tail = null;
                return null;
            }
            else {
                value = head.getData();
                /**
                 * 此处优化非常的美妙, 一句话抵得上peek()方法中的4句
                 *  node = head;
                 *  next = head.next;
                 *  head.next = null;
                 *  head = next;
                 */
                head = head.next;
                size--;
            }
            return value;
        }
    
        //设置链表元素
        public void offer (V data) {
            Node node = new Node(data);
            if (tail == null) {
                head = node;
                tail = node;
            }
            else {
                tail.next = node;
                tail = node;
            }
            size++;
        }
    
        public static void main(String[] args) {
            SingleNodeQueue<Integer> queue = new SingleNodeQueue<>();
            queue.offer(1);
            queue.offer(2);
            queue.offer(3);
            System.out.println(queue.size());
    
            do {
                System.out.println("获取单向队列的元素: " + (queue.peek()));
                System.out.println("测试当前队列长度" + queue.size());
            }while(queue.size() > 0);
    
    
            System.out.println("================测试泛型,优化后的peek================================");
    
            SingleNodeQueue<String> queue1 = new SingleNodeQueue<>();
            queue1.offer("test 1");
            queue1.offer("test 2");
            queue1.offer("test 3");
            System.out.println(queue1.size());
    
            do {
                System.out.println("获取单向队列的元素: " + (queue1.peek1()));
                System.out.println("测试当前队列长度" + queue1.size());
            }while(queue1.size() > 0);
    
    
        }
    }

    打印结果如下:

    3
    获取单向队列的元素: 1
    测试当前队列长度2
    获取单向队列的元素: 2
    测试当前队列长度1
    获取单向队列的元素: 3
    测试当前队列长度0
    ================测试泛型,优化后的peek================================
    3
    获取单向队列的元素: test 1
    测试当前队列长度2
    获取单向队列的元素: test 2
    测试当前队列长度1
    获取单向队列的元素: test 3
    测试当前队列长度0
    
    Process finished with exit code 0

     

  • 下面继续延伸。题目 “使用双向链表的知识,设计一个双向队列。要求是队列的头和队列的尾,都可以添加数据并且取数据
    package code.code_02;
    
    /**
     * 使用双链表设计一个双向队列,使对象的头节点和尾节点都可以
     * 添加/弹出节点元素
     */
    public class DoubleNodeQueue<V> {
    
        private Node<V> head; //当前队列的头
        private Node<V> tail;   //当前队列的尾
        private int size;
    
        public DoubleNodeQueue() {
            head = null;
            tail = null;
            size = 0;
        }
    
        //双链表
        private static class Node<V> {
            public V data;
            public Node<V> last;
            public Node<V> next;
    
            Node (V _data){
                this.data = _data;
            }
            public V getData() {
                return data;
            }
        }
    
        public boolean isEmpty () {
            return size == 0 ? true : false;
        }
    
        public int size () {
            return size;
        }
    
        //从队列头部取元素
        public V peekHead ()
        {
            V value = null;
            if (head == null) {
                System.out.println("当前队列还没有设置元素");
                tail = null;
                return value;
            }
            else {
                value = head.getData();
                //此时, 队列的第二个元素成为新的
                //头节点head
                head = head.next;
                size--;
            }
            return value;
        }
    
        //从队列尾部取元素
        public V peekTail ()
        {
            V value = null;
            if (tail == null) {
                System.out.println("当前队列还没有设置元素");
                return value;
            }
            else {
                value = tail.getData();
                //如果头和尾相等,说明队列只有一个元素
                //等价与tail.last == null;
                if (head == tail) {
                    head = null;
                    tail = null;
                } else {
                    tail = tail.last;
                    tail.next = null;
                }
                size--;
            }
            return value;
        }
    
        //从尾节点添加队列元素
        public void pushTail (V data) {
            Node<V> node = new Node<>(data);
            if (head == null) {
                head = node;
                tail = node;
            }
            else {
                tail.next = node;
                //双向链表组成的队列新增部分
                //当前节点需要持有之前的尾结点对象引用
                node.last = tail;
                //添加完成以后, 尾节点需要移动到新添加的节点node处,
                //此时,新添加的node成为尾节点tail
                tail = node;
            }
            size++;
        }
    
        //从头节点添加队列元素
        public void pushHead (V data) {
            Node<V> node = new Node<>(data);
            if (head == null) {
                head = node;
                tail = node;
            }
            else {
                /**
                 * 从头结点添加队列新元素,那么之前的头节点变成第二个元素
                 * 因此,之前的头结点head.last需要持有新节点对象引用node
                 * 新节点node.next需要持有之间的头结点
                 */
                head.last = node;
                node.next = head;
                //添加完成以后, 头节点需要移动到新添加的节点node处,
                //此时,新添加的node成为头节点head
                head = node;
            }
            size++;
        }
    
        public static void main(String[] args) {
            DoubleNodeQueue<Integer> queue = new DoubleNodeQueue<>();
            //demo1, 测试从尾部添加元素,头部获取元素。 先进先出
            queue.pushTail(1);
            queue.pushTail(2);
            queue.pushTail(3);
    
            System.out.println("=============测试双向队列尾部添加元素,头部取元素—----先进先出==========================");
            do {
                System.out.println("获取单向队列的元素: " + (queue.peekHead()));
            }while(queue.size > 0);
    
            //demo2, 测试从尾部添加元素,从尾部获取元素
            queue.pushTail(-1);
            queue.pushTail(-2);
            queue.pushTail(-3);
    
            System.out.println("=============测试双向队列尾部添加元素,尾部获取元素—----后进先出==========================");
            do {
                System.out.println("获取单向队列的元素: " + (queue.peekTail()));
            }while(queue.size > 0);
    
            //demo3, 测试从头部添加元素,头部取元素
            queue.pushHead(11);
            queue.pushHead(12);
            queue.pushHead(13);
            System.out.println("=============测试双向队列头部添加元素,头部获取元素—----后进先出==================");
            do {
                System.out.println("获取单向队列的元素: " + (queue.peekHead()));
            }while(queue.size > 0);
    
            //demo4, 测试从头部添加元素, 尾部取元素
            queue.pushHead(21);
            queue.pushHead(22);
            queue.pushHead(23);
            System.out.println("=============测试双向队列头部添加元素,尾部获取元素—----先进先出==========================");
            do {
                System.out.println("获取单向队列的元素: " + (queue.peekTail()));
            }while(queue.size > 0);
    
        }
    }

    打印信息如下:

  • =============测试双向队列尾部添加元素,头部取元素—----先进先出==========================
    获取单向队列的元素: 1
    获取单向队列的元素: 2
    获取单向队列的元素: 3
    =============测试双向队列尾部添加元素,尾部获取元素—----后进先出==========================
    获取单向队列的元素: -3
    获取单向队列的元素: -2
    获取单向队列的元素: -1
    =============测试双向队列头部添加元素,头部获取元素—----后进先出==================
    获取单向队列的元素: 13
    获取单向队列的元素: 12
    获取单向队列的元素: 11
    =============测试双向队列头部添加元素,尾部获取元素—----先进先出==========================
    获取单向队列的元素: 21
    获取单向队列的元素: 22
    获取单向队列的元素: 23
    
    Process finished with exit code 0

     

  • 有了单链表的实现,相信双链表实现也能理解。如果此算法有问题,说明链表的知识掌握的还不够牢靠,请先看算法2的相关知识 https://www.cnblogs.com/chen1-kerr/p/16905803.html

原文地址:http://www.cnblogs.com/chen1-kerr/p/16909869.html

1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长! 2. 分享目的仅供大家学习和交流,请务用于商业用途! 3. 如果你也有好源码或者教程,可以到用户中心发布,分享有积分奖励和额外收入! 4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解! 5. 如有链接无法下载、失效或广告,请联系管理员处理! 6. 本站资源售价只是赞助,收取费用仅维持本站的日常运营所需! 7. 如遇到加密压缩包,默认解压密码为"gltf",如遇到无法解压的请联系管理员! 8. 因为资源和程序源码均为可复制品,所以不支持任何理由的退款兑现,请斟酌后支付下载 声明:如果标题没有注明"已测试"或者"测试可用"等字样的资源源码均未经过站长测试.特别注意没有标注的源码不保证任何可用性