上篇博客和大家分享了java的链表实现,这篇博客将和大家一起分享基于链表的栈和队列。这里可以先回忆一下基于动态数组实现的栈和队列,无论是底层是链表还是动态数组,栈和队列的接口都是一致的。
首先,我们一起来看以前定义的栈的接口
public interface StackInterface<E> {
E pop();
E peek();
void push(E e);
boolean isEmpty();
int getSize();
}
相信大家一定不陌生,接下来,让我们一起看看如何使用链表实现栈,由于我们在链表中已经封装好一些方法,所以实现栈其实是很简单的
public class LinkedListStack<E> implements StackInterface<E> {
private LinkedList<E> list;
public LinkedListStack() {
list = new LinkedList<>();
}
@Override
public E pop() {
return list.removeFirst();
}
@Override
public E peek() {
return list.getFist();
}
@Override
public void push(E e) {
list.addFirst(e);
}
@Override
public boolean isEmpty() {
return list.isEmpty();
}
@Override
public int getSize() {
return list.getSize();
}
@Override
public String toString() {
StringBuilder res = new StringBuilder();
res.append("Stack: top ");
res.append(list);
return res.toString();
}
}
既然基于链表的栈已经被轻松拿下,那么队列一定也不会难住我们,我们还是先看以前定义好的队列的接口
public interface QueueInterface<E> {
int getSize();
boolean isEmpty();
void enqueue(E e);
E dequeue();
E getFront();
}
同样根据队列的定义,使用我们在链表里封住好的方法
public class LinkedListQueue<E> implements QueueInterface<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() {
head = null;
tail = null;
size = 0;
}
@Override
public int getSize() {
return size;
}
@Override
public boolean isEmpty() {
return size == 0;
}
@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++;
}
@Override
public E dequeue() {
if (isEmpty()) {
throw new IllegalArgumentException("Cannot dequeue from an empty queue.");
}
Node retNode = head;
head = head.next;
retNode.next = null;
if (head == null) {
tail = null;
}
size--;
return retNode.e;
}
@Override
public E getFront() {
if (isEmpty()) {
throw new IllegalArgumentException("Cannot dequeue from an empty queue.");
}
return head.e;
}
@Override
public String toString() {
StringBuilder res = new StringBuilder();
Node cur = head;
while (cur != null) {
res.append(cur + "->");
cur = cur.next;
}
res.append("NULL tail");
return res.toString();
}
}
这里需要注意的是,我们在链表的尾部添加了一个tail节点,因为队列是先进先出的结构,不同于栈,我们只需要操作头节点就可以了,在入队操作时,如果没有队尾的引用,那么每次都需要遍历整个链表,是O(n)的复杂度,所以引入了tail节点。
到了这里,同学们对于线性数据结构,应该会有一些新的认识,但是只有线性结构,往往是不够的,下一篇博客,将和大家一起分享一种新的数据结构,树结构。感谢阅读~
还请需要转载的同学注明出处:https://blog.csdn.net/sinat_33150417/article/details/82492809