教你如何使用Java手写一个基于链表的队列
在上一篇博客【教你如何使用Java手写一个基于数组的队列】中已经介绍了队列,以及Java语言中对队列的实现,对队列不是很了解的可以我上一篇文章。那么,现在就直接进入主题吧。
这篇博客主要讲解的是如何使用单链表实现一个简单版的队列。单向链表队列是属于非循环队列,同时队列的长度是不受限制的,也就是说添加数据的速度比拉取数据的速度快时,队列的长度是无限增长的。单链队列其本质就是一个链表,只不过是在获取或添加数据的时候跟普通的链表有所区别,队列在获取数据的同时也将该节点删除,并且每次获取数据都是从表头获取,普通链表可以获取任意节点的数据;队列在增加数据时总是添加到链表的尾部,而普通的链表则是可以在链表的任意地方插入一个节点。
一、队列数据结构
该队列的结构够多个节点构成,每个节点都有一个指向下一个节点的指针,使得所有的节点都能够相连,形成一个链表。具体结构如下如:

Java实现:
static class Node{
Object item;
Node next;
public Node(Object item, Node next) {
this.item = item;
this.next = next;
}
}
其实就创建一个静态内部类即可,类中item是用来存储数据的,next是指向下一个node节点,最后一个节点的next为空。
二、属性
head:链表表头,拉取或遍历数据都是从这里开始的。
tail:链表表尾,每次添加数据都添加到tail的后面,变成新的tail
size:队列长度
//表头
private Node head;
//表尾
private Node tail;
//队列长度
private int size;
三、添加数据
public void offer(Object item){
Node n = new Node(item,null);
if (tail == null){
head = tail = n;
}else {
tail.next = n;
tail = n;
}
size++;
}
用代码实现队列的添加操作看起是很简单的,无非就是将新节点添加到表尾,然后把新节点设置成新的表尾。
四、拉取数据
public Object poll(){
if (head == null) return null;
Node h = head;
//将拉取的节点的下一个节点变成新的表头
head = head.next;
//把旧的表头的下一个节点指向设置为null,让gc回收
h.next = null;
//队列为空
if (head == null)
tail = null;
size--;
return h.item;
}
五、查看数据
public Object peek(){
return head == null ? null : head.item;
}
查看数据看的是表头的数据,但是跟poll方法的区别是该方法不会删除表头的数据。
六、清空列表
public void clear(){
size = ;
Node h = head;
while (h != null){
Node temp = h.next;
h.next = null;
h = temp;
}
head = tail = null;
}
七、基于数组的队列和链表的队列的区别
1、前者是有边界的循环队列,后者则是没有边界的非循环队列。
2、前者在添加数据时无需创建新对象,性能消耗相对较小,后者每次添加数据都需要创建新对象。
3、后者每个节点都维护了一个链,所以所需内存也相对较大。
4、如果添加速度大于拉取速度,前者在达到边界后可能会无法添加数据,后者则没有这个问题。
八、完整代码
/**
* 基于链表实现的队列
*/
public class LinkQueue { //表头
private Node head;
//表尾
private Node tail;
//队列长度
private int size; public LinkQueue(){} public void offer(Object item){
Node n = new Node(item,null);
if (tail == null){
head = tail = n;
}else {
tail.next = n;
tail = n;
}
size++;
} public Object poll(){
if (head == null) return null;
Node h = head;
//将拉取的节点的下一个节点变成新的表头
head = head.next;
//把旧的表头的下一个节点指向设置为null,让gc回收
h.next = null;
//队列为空
if (head == null)
tail = null;
size--;
return h.item;
} public Object peek(){
return head == null ? null : head.item;
} public void clear(){
size = ;
Node h = head;
while (h != null){
Node temp = h.next;
h.next = null;
h = temp;
}
head = tail = null;
} public int size(){return size;} static class Node{
Object item;
Node next; public Node(Object item, Node next) {
this.item = item;
this.next = next;
}
} @Override
public String toString() {
if (size == ) return "{}";
StringBuilder builder = new StringBuilder(size + );
Node h = head;
builder.append("{");
while (h != null){
builder.append(h.item);
builder.append(", ");
h = h.next;
}
return builder.substring(,builder.length() -) + "}";
}
}
教你如何使用Java手写一个基于链表的队列的更多相关文章
- 教你如何使用Java手写一个基于数组实现的队列
一.概述 队列,又称为伫列(queue),是先进先出(FIFO, First-In-First-Out)的线性表.在具体应用中通常用链表或者数组来实现.队列只允许在后端(称为rear)进行插入操作,在 ...
- 手把手教你手写一个最简单的 Spring Boot Starter
欢迎关注微信公众号:「Java之言」技术文章持续更新,请持续关注...... 第一时间学习最新技术文章 领取最新技术学习资料视频 最新互联网资讯和面试经验 何为 Starter ? 想必大家都使用过 ...
- 【spring】-- 手写一个最简单的IOC框架
1.什么是springIOC IOC就是把每一个bean(实体类)与bean(实体了)之间的关系交给第三方容器进行管理. 如果我们手写一个最最简单的IOC,最终效果是怎样呢? xml配置: <b ...
- 搞定redis面试--Redis的过期策略?手写一个LRU?
1 面试题 Redis的过期策略都有哪些?内存淘汰机制都有哪些?手写一下LRU代码实现? 2 考点分析 1)我往redis里写的数据怎么没了? 我们生产环境的redis怎么经常会丢掉一些数据?写进去了 ...
- 利用SpringBoot+Logback手写一个简单的链路追踪
目录 一.实现原理 二.代码实战 三.测试 最近线上排查问题时候,发现请求太多导致日志错综复杂,没办法把用户在一次或多次请求的日志关联在一起,所以就利用SpringBoot+Logback手写了一个简 ...
- java 手写 jvm高性能缓存
java 手写 jvm高性能缓存,键值对存储,队列存储,存储超时设置 缓存接口 package com.ws.commons.cache; import java.util.function.Func ...
- 看年薪50W的架构师如何手写一个SpringMVC框架
前言 做 Java Web 开发的你,一定听说过SpringMVC的大名,作为现在运用最广泛的Java框架,它到目前为止依然保持着强大的活力和广泛的用户群. 本文介绍如何用eclipse一步一步搭建S ...
- 摊牌了!我要手写一个“Spring Boot”
目前的话,已经把 Spring MVC 相关常用的注解比如@GetMapping .@PostMapping .@PathVariable 写完了.我也已经将项目开源出来了,地址:https://gi ...
- 手写一个最迷你的Web服务器
今天我们就仿照Tomcat服务器来手写一个最简单最迷你版的web服务器,仅供学习交流. 1. 在你windows系统盘的F盘下,创建一个文件夹webroot,用来存放前端代码. 2. 代码介绍: ( ...
随机推荐
- DjangoRestFramework的外键反向关系序列化的一个问题
先用文档中的样例: Models定义: class Album(models.Model): album_name = models.CharField(max_length=100) artist ...
- Android开发之深入理解Android 7.0系统权限更改相关文档
http://www.cnblogs.com/dazhao/p/6547811.html 摘要: Android 6.0之后的版本增加了运行时权限,应用程序在执行每个需要系统权限的功能时,需要添加权限 ...
- Linux的动态库与静态库
1.动态库与静态库简介 在实际的软件开发中,为了方便使用一些被重复调用的公共代码,我们经常将这些公共的函数编译成动态库或静态库.我们知道程序一般要经过预处理.编译.汇编和链接这几个步骤才能变成可执行的 ...
- git 使用简易指南
- api大全
免费api大全(更新中) API大全 http://www.apidq.com/ (这个碉堡了) 天气接口 气象局接口 完整数据:http://m.weather.com.cn/data/10 ...
- Quartz学习--二 Hello Quartz! 和源码分析
Quartz学习--二 Hello Quartz! 和源码分析 三. Hello Quartz! 我会跟着 第一章 6.2 的图来 进行同步代码编写 简单入门示例: 创建一个新的java普通工程 ...
- [Kali_Metasploit]db_connect创建连接时无法连接的解决方案
问题1复现路径: postgresql selected, no connection 第一步: db_connect postgres:toor@127.0.0.1/msfbook 连接成功不需要进 ...
- Makefile基础---编译
首先写一个自己的库: #include "../MyAPI.h" #include <cstdlib> #include <ctime> int getRa ...
- 用redis的scan命令代替keys命令,以及在spring-data-redis中遇到的问题
摘要 本文主要是介绍使用redis scan命令遇到的一些问题总结,scan命令本身没有什么问题,主要是spring-data-redis的问题. 需求 需要遍历redis中key,找到符合某些pat ...
- SpringMVC中参数绑定
SpringMVC中请求参数的接收主要有两种方式, 一种是基于HttpServletRequest对象获取, 另外一种是通过Controller中的形参获取 一 通过HttpServletReque ...