队列之单向链表与双向链表的模拟实现

简介: 队列之单向链表与双向链表的模拟实现

队列:只允许在一端进行插入的操作,在另一端进行删除数据操作的特殊线性表,队列具有先进先出的原则!!

进行插入操作的一端称为对胃!

进行删除操作的一端称为对头!

经过上面的一些讲解,那么我们可以来用单链表来实现一个队列了吧!!

头插法O(1)

删除链表最后一个元素O(N)

尾插法O(N)

删除头部元素O(1)

因此,有着一些局限:只能从尾巴插入,头部删除!(找到尾巴节点,头部节点)

有着上述分析,开始用单链表实现链式队列吧!!

单链表实现队列
public class MyQueue {
    //用单链表实现链式队列
    static class Node{
        //单链表
        public int val;
        public Node next;
        //构造方法
        public Node(int val){
            this.val=val;
        }
    }
    public Node head;//头
    public Node last;//尾
    public int usedSize;
    //入队
    public void offer(int val){
        Node node=new Node(val);
        if (head==null){
            head=node;
            last=node;
        }else {
            last.next=node;
            last=node;
        }
        usedSize++;
    }
    //出队
    public int poll(){
        if (empty()){//判断是否为空
            throw new EmptyException("队列为空");
        }
        int ret=head.val;//想要出队的值
        head=head.next;//头节点,走一步,删除原来的节点
        if (head==null){
            //只有一个节点
            last=null;
        }
        usedSize--;
        return ret;
    }
    //判断是否为空
    public boolean empty(){
        return usedSize==0;
    }
    //偷看头节点
    public int peek(){
        if (empty()){
            throw new EmptyException("对列为空");
        }
        return head.val;
    }
    public int getUsedSize(){
        return usedSize;
    }
}

在这个代码中,用链表来实现的队列,基本上都是链表的基础知识,没有多大的新意!

首先定义链表的头,尾,节点的个数,从入队列开始实现,因为队列是先进先出的模式,那么,我们在链表中,就可以进行尾插,每次插入的时候,都将数据插入到链表的后面,并且每次插入都得记录一下此时的链表长度(usedSize++)!在出队列的过程中,由于队列的先进先出模式,所以在单向链表实现的过程中,我们也要遵循这个先进先出的模式,那么,这就要求我们,每次进行出链表的时候,都得出掉链表的头部(头删),同时usedSize--;头节点往后走一步!在进行偷看头节点的操作的时候,这就显得很简单了!但是,这个需要注意一个大前提:链表不能为空!如果链表不为空,之间返回链表的头节点即可!

抛异常的代码为:

public class EmptyException extends RuntimeException {
    public EmptyException() {
    }
    public EmptyException(String message) {
        super(message);
    }
}

抛异常的操作,有一个不带参数的构造方法,也有一个带有一个参数的构造方法!

Main方法的代码为:

public class Test {
    public static void main(String[] args) {
        MyQueue myQueue=new MyQueue();
        myQueue.offer(12);
        myQueue.offer(23);
        myQueue.offer(34);
        myQueue.offer(45);
        myQueue.offer(45);
        System.out.println(myQueue.peek());
        System.out.println(myQueue.poll());
        System.out.println(myQueue.poll());
        System.out.println(myQueue.poll());
    }
}

代码的运行结果为:

双向链表实现队列

用双向链表来实现一个栈的前提,是我们需要知道栈的底层是一个双向链表!!

public class Queue {
    //用双向链表实现一个队列
    public static class ListNoode{
        //双向链表的各个节点
        ListNoode next;//下一个
        ListNoode prev;//上一个
        int val;
    }
    ListNoode first;//对头
    ListNoode last;//队尾
    int size=0;
    //入队列,向双向链表位置插入新的节点
    public void offer(int e){
        ListNoode newNode=new ListNoode();
        if (first==null){
            first=newNode;
            last=newNode;
        }else {
            last.next=newNode;
            newNode.prev=last;
            last=newNode;
        }
        size++;
    }
    //出队列,将双向链表的第一个节点删除掉
    public int poll(){
        //1.队列为空
        //2,队列只有一个元素——》链表中只有一个节点——》直接删除
        //3,队列中有多个元素——》链表中有多个节点——》将第一个节点删除
        int value=0;
        if (first==null){
            return null;
        }else if (first==last){
            last=null;
            first=null;
        }else {
            value=first.val;
            first=first.next;
            first.prev.next=null;
            first.prev=null;
        }
        --size;
        return value;
    }
    //获取对头元素——》获取链表中第一个节点的值域
    public int peek(){
        if (first==null){
            return null;
        }
        return first.val;
    }
    public int size(){
        return size;
    }
    public boolean isEmpty(){
        return first==null;
    }
}

在用双向链表实现队列的时候,其实跟单向链表实现队列差不多!!主要还是双向链表比单向链表多了一个域:用来记录前一个节点的地址!!这个就导致我们在进行插入/删除数据的时候,就得多思考一下了!!但是,由于:栈的底层是一个双向链表,那么,我们就得学好双向链表了!!

相关文章
|
2月前
|
存储 算法 搜索推荐
探索常见数据结构:数组、链表、栈、队列、树和图
探索常见数据结构:数组、链表、栈、队列、树和图
122 64
|
27天前
|
存储 缓存 算法
在C语言中,数据结构是构建高效程序的基石。本文探讨了数组、链表、栈、队列、树和图等常见数据结构的特点、应用及实现方式
在C语言中,数据结构是构建高效程序的基石。本文探讨了数组、链表、栈、队列、树和图等常见数据结构的特点、应用及实现方式,强调了合理选择数据结构的重要性,并通过案例分析展示了其在实际项目中的应用,旨在帮助读者提升编程能力。
53 5
|
2月前
|
存储
【初阶数据结构】深入解析单链表:探索底层逻辑(无头单向非循环链表)(一)
【初阶数据结构】深入解析单链表:探索底层逻辑(无头单向非循环链表)
|
2月前
|
算法 Java
数据结构与算法学习六:单向环形链表应用实例的约瑟夫环问题
这篇文章通过单向环形链表的应用实例,详细讲解了约瑟夫环问题的解决方案,并提供了Java代码实现。
29 0
|
2月前
|
存储 缓存
【初阶数据结构】深入解析单链表:探索底层逻辑(无头单向非循环链表)(二)
【初阶数据结构】深入解析单链表:探索底层逻辑(无头单向非循环链表)
|
4月前
|
存储 Java
|
4月前
|
存储 JavaScript 前端开发
JavaScript实现单向链表
JavaScript实现单向链表
25 0
|
5月前
链表8(法二考试专用)7-8 sdut-C语言实验-双向链表
链表8(法二考试专用)7-8 sdut-C语言实验-双向链表
25 0
|
5月前
sdut 链表 8 -----7-8 sdut-C语言实验-双向链表
sdut 链表 8 -----7-8 sdut-C语言实验-双向链表
25 0