Java语言实现基于链表的动态队列

本文是一篇用Java实现的基于链表的动态队列,使用范型
首先了解一下什么是队列:
引用百度百科:队列是一种特殊的线性表,特殊之处在于它只允许在表的前端(front)进行删除操作,而在表的后端(rear)进行插入操作,和栈一样,队列是一种操作受限制的线性表。进行插入操作的端称为队尾,进行删除操作的端称为队头。
再了解一下什么是链表:
还是引用百度百科:链表是一种物理存储单元上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。链表由一系列结点(链表中每一个元素称为结点)组成,结点可以在运行时动态生成。每个结点包括两个部分:一个是存储数据元素的数据域,另一个是存储下一个结点地址的指针域。 相比于线性表顺序结构,操作复杂。由于不必须按顺序存储,链表在插入的时候可以达到O(1)的复杂度,比另一种线性表顺序表快得多,但是查找一个节点或者访问特定编号的节点则需要O(n)的时间,而线性表和顺序表相应的时间复杂度分别是O(logn)和O(1)。
看完估计有明白的有不明白的,不明白的话就先去了解一下链表和队列吧,本文就不详细普及这两个概念了。
这是我的数据结构练习的github地址,里面会不断更新各种数据结构的java实现,喜欢的话记得star

队列接口YgzQueue

public interface YgzQueue<E> {

    //获取队列长度
    int size();

    //队列是否为空
    boolean isEmpty();

    //给队尾添加一个元素
    void enqueue(E e);

    //取出队首元素
    E dequeue();

    //获取队首的元素
    E getFront();

}

基于链表的队列实现YgzLinkedQueue

	/**
	 * 基于链表实现的队列
	 */
	public class YgzLinkedQueue<E> implements YgzQueue<E>{
	
	    /**
	     * 节点对象
	     */
	    private class Node{
	
	        //链表的某个节点的实际值
	        public E e;
	
	        //链表某个节点的下一个节点
	        public Node next;
	
	        public Node(E e, Node next){
	            this.e = e;
	            this.next = next;
	        }
	
	        public Node(E e){
	            this(e, null);
	        }
	
	        public Node(){
	            this(null, null);
	        }
	
	        @Override
	        public String toString(){
	            return e.toString();
	        }
	    }
	
	    //链表的头节点和尾节点
	    private Node head, tail;
	
	    private int size;
	
	    /**
	     * 无参构造
	     */
	    public YgzLinkedQueue(){
	        head = null;
	        tail = null;
	        size = 0;
	    }
	
	    /**
	      * @Author: Ygz
	      * @Description:获取队列的内容数量
	      * @Date:2018/6/24 19:15
	      * @Param:[]
	      * @return int
	      */
	    @Override
	    public int size() {
	        return size;
	    }
	
	    /**
	      * @Author: Ygz
	      * @Description:队列是否为空
	      * @Date:2018/6/24 19:15
	      * @Param:[]
	      * @return boolean
	      */
	    @Override
	    public boolean isEmpty() {
	        return size == 0;
	    }
	
	    /**
	      * @Author: Ygz
	      * @Description:队列尾新增一个元素,即入队
	      * @Date:2018/6/24 19:15
	      * @Param:[e]
	      * @return void
	      */
	    @Override
	    public void enqueue(E e) {
	        //下面描述一下  我这个基于链表队列,链表是有head和tail的,
	        // 但是在链表头新增和删除元素时间复杂度都是O(1),在链表尾添加元素也是O(1),但是在链表尾删除元素的时候
	        // 由于是单向链表  链表尾不知道它自己的前一个元素节点  所以删除链表尾的元素时间复杂度会变成O(n)
	        // 这样的话  这里做一个变换
	        // 我们从链表头删除元素(出队)  链表尾新增元素(入队)
	        // 这样根据队列先进先出的特性  这个基于链表的队列不管是出队还是入队
	        // 时间复杂度都是O(1)  操作如下:
	        if(tail == null){           //如果队尾为null  说明队列为空
	            tail = new Node(e);     //new Node给队尾
	            head = tail;            //队首和队尾一样
	        }else{
	            tail.next = new Node(e);//给队尾的下一个赋值new Node 相当于给队尾的位置添加一个元素
	            tail = tail.next;       //更新tail队尾的值
	        }
	        size ++;
	    }
	
	    /**
	      * @Author: Ygz
	      * @Description:队列首出去一个元素,即出队
	      * @Date:2018/6/24 19:36
	      * @Param:[]
	      * @return E
	      */
	    @Override
	    public E dequeue() {
	        if(this.isEmpty())
	            throw new IllegalArgumentException("队列为空,dequeue失败。");
	        Node res = head;        //首先拿到队首的元素  准备出队留作return
	        head = head.next;       //然后更新head为head的下一个(next)
	        res.next = null;        //要出队的节点的下一个(next)变为null
	        if(head == null)        //这里要注意  经过上一步  head == null 说明队列之前只有1个元素了
	            tail = null;        //所以要更新tail也变成null
	        size--;
	        return res.e;
	    }
	
	    /**
	      * @Author: Ygz
	      * @Description:查看队列的队首元素
	      * @Date:2018/6/24 19:57
	      * @Param:[]
	      * @return E
	      */
	    @Override
	    public E getFront() {
	        if(this.isEmpty())
	            throw new IllegalArgumentException("队列为空,getFront失败。");
	        return head.e;
	    }
	
	    @Override
	    public String toString(){
	        StringBuilder res = new StringBuilder();
	        res.append("YgzLinkedQueue: head  ");
	        Node cur = head;
	        while(cur != null) {
	            res.append(cur + "->");
	            cur = cur.next;
	        }
	        res.append(" tail");
	        return res.toString();
	    }
	}

好了 到这就完了 代码复制过去直接运行应该都是可以的 运行都有注释的 希望能帮助到大家 再说一下 我这个只是一个简单的实现 这个还可以做很多的优化 不喜勿喷
这是我的数据结构练习的github地址,里面会不断更新各种数据结构的java实现,喜欢的话记得star

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
### 回答1: 循环队列是一种特殊的队列,它采用了循环数组的方式来实现队列的操作。在串口通信中,使用循环队列可以有效地解决串口信息收发的问题。 首先,我们需要使用Java提供的串口通信库,如RXTX或JSerialComm,来创建串口对象,并设置好串口的相关参数,如波特率、数据位、校验位和停止位等。 然后,我们可以使用循环队列实现串口信息的收发。循环队列有两个指针,一个指向队头,一个指向队尾,分别称为front和rear。我们可以将接收到的串口数据存放在队列中,并通过循环队列的rear指针来指示最后一个数据的位置。 当有新的串口数据到达时,我们将其添加到队列中,并将rear指针后移一个位置。如果rear指针已经到达队列的最大容量,则将其重置为0,实现循环的效果。 同时,我们可以使用一个线程不断地检测队列中是否有数据需要发送。当有数据需要发送时,我们将其从队列中取出,并通过串口对象将数据发送出去。 在接收端,我们可以使用另一个线程来不断地监听串口,当接收到数据时,将其添加到队列中,并将front指针后移一个位置。如果front指针已经到达队列的最大容量,则将其重置为0,实现循环的效果。 通过循环队列的方式,我们可以实现串口信息的收发,并保证数据的顺序和完整性。同时,循环队列还可以避免数据的溢出和浪费,提高了串口通信的效率和稳定性。 因此,利用循环队列可以很好地解决串口信息收发的问题。 ### 回答2: 串口通信是指通过串行通信接口与外部设备进行数据交换的过程。在Java中,可以使用循环队列来解决串口信息收发问题。 循环队列是一种环形数据结构,它可以实现数据的连续存储和高效读写操作。对于串口通信来说,循环队列可以实现接收数据的缓存和发送数据的队列。 在串口信息接收方面,循环队列可以起到缓存的作用。当接收到串口数据时,可以将数据存入循环队列中,然后从队列中读取数据进行后续处理。这样可以有效地解决数据丢失和数据处理速度不匹配的问题。 在串口信息发送方面,循环队列可以起到队列的作用。将要发送的数据存入循环队列中,然后从队列中读取数据发送到串口。这样可以实现将发送数据按顺序发送,并且可以通过设置队列长度来控制发送速度,避免数据丢失和发送速度过快导致的问题。 在Java中,可以使用队列接口和相应的实现类来实现循环队列。可以使用ArrayDeque类实现基于数组的循环队列,也可以使用LinkedList类实现基于链表的循环队列。在使用循环队列时,需要注意队列长度的设置、队列是否为空或满的判断,并且需要实现读写指针的更新。 总之,通过Java中的循环队列,可以很好地解决串口信息收发问题。循环队列可以实现串口数据的缓存和队列管理,保证数据的稳定传输和顺序处理。而且,在Java使用循环队列也比较简单,只需使用相应的队列接口和实现类,结合合适的判断和更新操作即可。 ### 回答3: java利用循环队列可以较好地解决串口信息收发问题。串口通信是一种特殊的通信方式,需要通过串口接收和发送数据。由于串口数据的不可预测性,我们无法确定何时能收到完整的数据包,因此需要一个缓冲区来存储接收到的数据。 循环队列是一种能够循环利用缓冲区空间的数据结构,它可以提高数据的利用率。在Java语言中,我们可以利用数组来实现循环队列。 首先,我们需要定义一个循环队列的数据结构,包括队列的大小和相关操作方法。其中,包括入队操作和出队操作。入队操作将接收到的串口数据存储到队列中,而出队操作将从队列中取出数据用于处理。 其次,我们需要在程序中创建一个串口监听器,用于监听串口数据的到来。一旦接收到串口数据,监听器将把数据存储到循环队列中。 接着,我们可以创建一个线程来处理循环队列中的数据。线程将不断从队列中取出数据,并进行相应的处理,如数据解析、数据处理、数据存储等等。 使用循环队列的好处是可以提高数据处理的效率和准确性。当数据快速到来时,循环队列可以迅速处理数据并释放空间,然后继续接收新的数据。而如果使用传统的队列结构,可能会导致队列溢出或者数据丢失的情况。 总结起来,在Java中利用循环队列解决串口信息收发问题,我们首先需要定义一个循环队列的数据结构,然后创建串口监听器来接收数据并存储到队列中,最后创建一个线程来处理队列中的数据。这样可以提高串口数据的处理效率和准确性。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值