栈和队列,双端队列,如何用链表实现双端队列,如何用双端队列实现栈和队列

栈和队列,双端队列,如何用链表实现双端队列?如何用双端队列实现栈和队列?

提示:链表用来干嘛?双端队列如何实现栈与队列?


栈:Stack

拿系统栈玩一下就知道栈是啥玩意了

Stack<Integer> stack = new Stack<>();
        stack.push(1);
        stack.push(2);
        System.out.println(stack.pop() +" "+ stack.pop());

结果:2 1
说明栈:是先进后出的数据结构:
在这里插入图片描述

队列:queue,LinkedList

也用系统队列玩一下:java中的队列是LinkedList,别整错了

Queue<Integer> queue = new LinkedList<>();
        queue.add(1);
        queue.add(2);

        System.out.println(queue.poll() +" "+ queue.poll());

结果:1 2
说明:队列是先进先出的数据结构
在这里插入图片描述

双端队列:链表实现双端队列

这个双端队列,系统没有,咱们自己定义:
双端队列,本身是队列,内部是一个双向链表,可以从头入,尾入,还可以从头出,尾出
这既是双端操作的意思:
在这里插入图片描述
我们来实现一下双端队列:DoubleEndsQueue2:T
T代表泛型数据类型:可以是String,Integer,随意
链表的节点:

//双向链表节点
    public static class Node<T> {
        public T value;//这个T就是任意形式的数据类型包括int啥的,Integer啥的,String等等
        //用的时候指定清楚这是啥类型就行
        public Node<T> last = null;//指向前一个节点的指针,与parent一个道理,
        // 未来在双向二叉树中就可以看到这种,有个父亲指针parent,有左子指针left,右子指针right
        public Node<T> next = null;//指向下一个几点的指针,

        //初始化,构造函数
        public Node(T v) {
            value = v;
        }
    }

——双端队列内部至少是一个双向链表,属性有head和tail维持这个链表
——函数有:
(1)从头部输入新节点value;
(2)从尾部输入新节点value;
(3)从头部输出节点value;
(4)从尾部输出节点value;

手撕双端队列的代码,这没啥可说,必须自己手撕会,就是达到:不看别人的代码,自己也要写出来,调试通过,验证正误:

//复习双端队列
    public static class DoubleEndsQueue2<T>{
        public Node<T> head;
        public Node<T> tail;

        public DoubleEndsQueue2(){
            head = null;
            tail = null;
        }

        //四个函数:
        //	(1)从头部输入新节点value;
        public void addFromHead(T value){
            //既然新来节点,那新建
            Node<T> cur = new Node<>(value);
            //如果之前压根没有节点
            if (head == null){
                //则此时cur既是head,又是tail
                head = cur;
                tail = cur;
            }else {
                //从头部输入,挂接,换头
                head.last = cur;
                cur.next = head;
                head = cur;
            }
        }

        //	(2)从尾部输入新节点value;
        public void addFromTail(T value){
            //既然新来节点,那新建
            Node<T> cur = new Node<>(value);
            //如果之前压根没有节点
            if (head == null){
                //则此时cur既是head,又是tail
                head = cur;
                tail = cur;
            }else{
                //从尾部接入,换尾
                tail.next = cur;
                cur.last = tail;
                tail = cur;
            }
        }

        //	(3)从头部输出节点value;
        public T popFromHead(){
            Node<T> cur = head;//head

            //就一个点
            if (head == tail) {
                head = null;
                tail = null;
            }else {
                //将head移动下一个位置,然后把cur与head断开
                head = cur.next;
                head.last = null;
                cur.next = null;
            }

            return cur.value;
        }

        //	(4)从尾部输出节点value;
        public T popFromTail(){
            Node<T> cur = tail;//tail

            //就一个点
            if (head == tail) {
                head = null;
                tail = null;
            }else {
                //将tail前移一个位置,然后将tail和cur断开,返回cur
                tail = cur.last;
                tail.next = null;
                cur.last = null;
            }

            return cur.value;
        }

        //判空
        public boolean isEmpty(){
            return head == null;//头结点都没有,那还用说,就是空呗
        }
    }

测试:

//测试双端队列的正误
    public static void test3(){
        DoubleEndsQueue2<Integer> queue2 = new DoubleEndsQueue2<>();
        queue2.addFromHead(1);//1
        queue2.addFromTail(2);//1 2
        queue2.addFromHead(3);//3 1 2
        queue2.addFromTail(4);//3 1 2 4
        Node<Integer> cur = queue2.head;
        while (cur != null){
            System.out.print(cur.value +" ");
            cur = cur.next;
        }
        System.out.println();

        //弹出
        Integer a = queue2.popFromHead();
        System.out.println(a);
        cur = queue2.head;
        while (cur != null){
            System.out.print(cur.value +" ");
            cur = cur.next;
        }
        System.out.println();

        //弹出
        Integer b = queue2.popFromTail();
        System.out.println(b);
        cur = queue2.head;
        while (cur != null){
            System.out.print(cur.value +" ");
            cur = cur.next;
        }
    }

public static void main(String[] args) {
        //test2();
        test3();
    }

结果:

3 1 2 4 
3
1 2 4 
4
1 2 

完全没有任何问题


请你使用双端队列实现系统栈和队列

双端队列实现系统栈

非常简单,你不是双端都可以操作吗???
栈:先进先出
干脆这样,我让头进,头出就行呗:
在这里插入图片描述
(1)栈中属性:属性,就是双端队列一个
(2)仨函数:isEmpyt()判断栈是否为空?
(3)仨函数:push(value)压入元素
(4)仨函数:pop()弹出元素

手撕代码:

//双端队列实现栈
    public static class ReviewStack<T>{
        //属性,就是双端队列一个
        public DoubleEndsQueue2 queue2;

        //构造时先生成一个双端队列
        public ReviewStack(){
            queue2 = new DoubleEndsQueue2<>();
        }

        //提供仨函数
        //(2)仨函数:isEmpyt()判断栈是否为空?
        public boolean isEmpty(){
            return queue2.isEmpty();//直接用双端队列的判断函数
        }

        //(3)仨函数:push(value)压入元素
        public void push(T value){
            queue2.addFromHead(value);//直接头入
        }

        //(4)仨函数:pop()弹出元素
        public T pop(){
            return (T) queue2.popFromHead();//头返回即可
        }
    }

    public static void test4(){
        ReviewStack<Integer> stack = new ReviewStack<>();
        stack.push(1);
        stack.push(2);
        System.out.println(stack.pop());
        System.out.println(stack.pop());
        System.out.println(stack.isEmpty());
    }

    public static void main(String[] args) {
        //test2();
        //test3();
        test4();
    }

看结果:

2
1
true

很完美

双端队列实现系统队列

和栈类似,栈是先进后出
队列是先进就先出
那头进,尾出就行了
在这里插入图片描述
一样,队列内部有一个双向队列:DoubleEndsQueue2
仨函数:
(1)add(value)头入元素
(2)poll()尾部输出元素
(3)判空isEmpty()

手撕代码:

//用双向队列实现队列
    public static class ReviewQueue<T>{
        public DoubleEndsQueue2<T> queue2;

        public ReviewQueue(){
            queue2 = new DoubleEndsQueue2<>();//属性,生成
        }
        //仨函数:
        //(1)add(value)头入元素
        public void add(T value){
            queue2.addFromHead(value);
        }

        //(2)poll()尾部输出元素
        public T poll(){
            return queue2.popFromTail();//尾部输出
        }

        //(3)判空isEmpty()
        public boolean isEmpty(){
            return queue2.isEmpty();
        }
    }

    public static void test5(){
        ReviewQueue<Integer> queue = new ReviewQueue<>();
        queue.add(1);
        queue.add(2);
        System.out.println(queue.poll());
        System.out.println(queue.poll());
        System.out.println(queue.isEmpty());
    }

    public static void main(String[] args) {
        //test2();
        //test3();
        //test4();
        test5();
    }

结果:

1
2
true

自然是美滋滋的


总结

提示:重要经验:

1)了解系统中的栈,和队列,栈:先进后出,队列:先进先出
2)双向队列底层就是双向链表的操作,增删两个,不过就是在head和tail上操作
3)利用双向队列可以轻易地实现栈和队列。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

冰露可乐

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值