链表实现的栈
底层链表的实现基于算法与数据结构之带头节点的链表的实现Java版
时间复杂度都为O(1),与算法与数据结构之基于数组的栈的实现Java版相同
操作:
public interface Stack<E> {
int getSize(); //元素个数
boolean isEmpty(); //是否为空
void push(E e); //入栈
E pop(); //返回出栈元素
E peek(); //返回栈顶元素
}
源码实现
public class LinkedListStack<E> implements Stack<E> {
private LinkedList<E> list;
public LinkedListStack(){
list = new LinkedList<>();
}
@Override
public int getSize(){
return list.getSize();
}
@Override
public boolean isEmpty(){
return list.isEmpty();
}
@Override
public void push(E e){
list.addFirst(e);
}
@Override
public E pop(){
return list.removeFirst();
}
@Override
public E peek(){
return list.getFirst();
}
@Override
public String toString(){
StringBuilder res = new StringBuilder();
res.append("Stack: top ");
res.append(list);
return res.toString();
}
}
链表实现队列
对于链表来说(参考:算法与数据结构之带头节点的链表的实现Java版),如果只对链表的头部进行增和删操作,时间复杂度是O(1),我们可以设置一个尾指针,指向链表最后一个元素,这样在链表尾部进行插入操作的时间复杂度为O(1),但是在尾部删除元素时,需要知道尾部元素的上一个元素,即使有尾指针,尾部删除元素的操作是O(n)的,对于队列来说,需要进行入队和出队,所以我们把链表的尾部作为队列的队尾,只进行插入元素,把链表的头部作为队列的队头,进行删除元素的,也就是出队的操作,时间复杂度和算法与数据结构之基于数组实现的数组队列和循环队列Java版中的循环队列是一样的
操作:
public interface Queue<E> {
void enqueue(E e);
E dequeue();
E getFront();
int getSize();
boolean isEmpty();
}
源码实现
public class LinkedListQueue<E> implements Queue<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("Queue is empty.");
return head.e;
}
@Override
public String toString(){
StringBuilder res = new StringBuilder();
res.append("Queue: front ");
Node cur = head;
while(cur != null) {
res.append(cur + "->");
cur = cur.next;
}
res.append("NULL tail");
return res.toString();
}
}