好多人都觉得为什么要自己写这样的数据结构,变成里面不是有吗?为什么要去写,有这个疑问,其实这个疑问这我的脑海中也存在了很长一段时间,本人是学习java编程的,直接看java的集合框架不行吗?这个时候如果你的水平到了还好。如果没有,你会发现你根本就理解不了编程语言里面数据结构,看了就忘掉了,也理解不了,学习了半个月编程里面的集合发现学不会,还要抱怨怎么可以这样,看了半个月都没有看懂,于是就放弃了。如果让我来分析缘由,那就是市面上已经发布的编程语言里面的数据结构(集合框架)都是王者水平(巅峰王者)的人写的,这样厉害的人写出的东西,你一个没有啥基础的编程人员(按照游戏段位排序:青铜),几天几个月就整的明明白白,如果这样都能会,只有一种可能,你是天才,不是普通人。
所以基于这样的分析,我们学习就是要先从没有进数据结构的大门到变得更够秀(进军白银段位以致更高的水平),所以简易版的练习过程是在必行,脚踏实地,方是走过漫漫长路的捷径之路,于此,便有了一些列的数据结构的简易版,今天分析由链表设计的队列。
简单的代码搭建及思维逻辑分析
public class LinkedListQueue<E> implements QueueDemo<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 LinkedListQueue() {
this.head=null;
this.tail=null;
this.size=0;
}
@Override
public int getSize() {
return size;
}
@Override
public boolean isEmpty() {
return size==0;
}
}
内部节点类为了存储队列引用而设计, 由于队列是头出尾进,所以需要设计head、tail头尾节点,用于管理出队和入队,size属性由于记录队列实时大小;而设计的出队和入队进行重点分析。
入队操作代码分析
代码如下:
@Override
public void enqueue(E e) {
if (tail==null){
tail=new Node(e);
head=tail;
}else {
tail.next=new Node(e);
tail=tail.next;
}
size++;
}
1、入队操作时在队尾进行,所以有tail进行管理,当队列中一个节点都没有的时候(tail=null),初始tail和head都为null,当有值进行入队的时候,创建新节点node赋值给tail,再将tail(尾)的引用赋值给head(头),size+1(size++); 2、当已经存在第一个节点,向后添加节点,代码如下:
tail.next=new Node(e);
tail=tail.next;
思维逻辑图如下:
3、最后将size++;
出队操作代码分析
代码如下:
@Override
public E dequeue() {
if (isEmpty())
throw new IllegalArgumentException("cannot ");
Node retNode=head;
head=head.next;
retNode.next=null;
if (head==null)
tail=null;
size--;
return retNode.e;
}
1、想要出队首先要查看队列里是否有元素,不为空;2、上面刚刚论述了入队需要tail来管理,那么出队现在就需要head(头)来管理:队列(尾进头出);代码分析:头元素赋值给零时引用retNode(也就是要移除的节点),之后head节点引用安全的指向零时引用之后,将head节点的下个节点作为head,即head=head.next,这个时候就需要将原来的节点Node与目前的head引用关系断开,所以将 retNode.next=null赋值为null.
之后就是出队的过程中,head为null了,代表队列已经为空了;代码如下:
if (head==null)
tail=null;
由于正常情况下,出队一直没有对tail进行引用管理,但是当队列里面只有一个节点,出队以后,head这个时候已经为null了,但是tail还是还是指向原来出队节点的引用,所以,这个时候需要将tail也设置为null.
3、之后做完上述操作以后进行size-1(size–),并把retNode.e的值返回回去。
查看头元素方法
队列有进队和出队,当然还有查询队首元素的方法。
1、判断队列是否为空;2、将head.e的值返回
@Override
public E getFront() {
if (isEmpty())
throw new IllegalArgumentException("Queue is empty. ");
return head.e;
}
写博不易,关注博客了解更多原创详情。