前言
LinkedList是一个继承于AbstractSequentialList的双向链表。它也可以被当作堆栈、队列或双端队列进行操作。
LinkedList 实现 List 接口,能对它进行队列操作。
LinkedList 实现 Deque 接口,即能将LinkedList当作双端队列使用。
LinkedList 实现了Cloneable接口,即覆盖了函数clone(),能克隆。
LinkedList 实现java.io.Serializable接口,这意味着LinkedList支持序列化,能通过序列化去传输。
LinkedList 是非同步的。
一、LinkedList可以作为LIFO(后进先出)的栈,作为LIFO的栈时,下表的方法等价:
栈方法 等效方法 push(e) addFirst(e) pop() removeFirst() peek() peekFirst()
/**
* 将LinkedList当作 LIFO(后进先出)的堆栈
*/
private void useLinkedListAsLIFO() {
// 新建一个LinkedList
LinkedList stack = new LinkedList();
// 将1,2,3,4添加到堆栈中
stack.push("1");
stack.push("2");
stack.push("3");
stack.push("4");
// 打印“栈”
System.out.println("stack:"+stack);
// 删除“栈顶元素”
System.out.println("stack.pop():"+stack.pop());
// 取出“栈顶元素”
System.out.println("stack.peek():"+stack.peek());
// 打印“栈”
System.out.println("stack:"+stack);
}
输出结果:
stack:[4, 3, 2, 1]
stack.pop():4
stack.peek():3
stack:[3, 2, 1]
二、LinkedList可以作为FIFO(先进先出)的队列,作为FIFO的队列时,下表的方法等价:
队列方法 等效方法
add(e) addLast(e)
offer(e) offerLast(e)
remove() removeFirst()
poll() pollFirst()
element() getFirst()
peek() peekFirst()
/**
* 将LinkedList当作 FIFO(先进先出)的队列
*/
private void useLinkedListAsFIFO() {
// 新建一个LinkedList
LinkedList queue = new LinkedList();
// 将10,20,30,40添加到队列。每次都是插入到末尾
queue.add("10");
queue.add("20");
queue.add("30");
queue.add("40");
// 打印“队列”
System.out.println("queue:"+queue);
// 删除(队列的第一个元素)
System.out.println("queue.remove():"+queue.remove());
// 读取(队列的第一个元素)
System.out.println("queue.element():"+queue.element());
// 打印“队列”
System.out.println("queue:"+queue);
}
输出结果:
queue:[10, 20, 30, 40]
queue.remove():10
queue.element():20
queue:[20, 30, 40]
三、使用两个栈实现一个队列
public class MyQueue<E> {
/*入队栈*/
private final Stack<E> inStack = new Stack<>();
/*出队栈*/
private final Stack<E> outStack = new Stack<>();
/**
* 入队
*
* @param e
*/
public void offer(E e) {
while (!outStack.isEmpty()) {
inStack.push(outStack.pop());
}
inStack.push(e);
}
/**
* 出队
*/
public void poll() {
while (!inStack.isEmpty()) {
outStack.push(inStack.pop());
}
outStack.pop();
}
/**
* 判断队列是否为空
*
* @return
*/
public boolean isEmpty() {
return inStack.isEmpty() && outStack.isEmpty();
}
/**
* 获取队列中的第一个元素
*
* @return
*/
public E peek() {
while (!inStack.isEmpty()) {
outStack.push(inStack.pop());
}
return outStack.peek();
}
}
四、用两个队列实现栈
思路:队列是先进先出,栈是先进后出。要想用队列实现栈,则需要两个队列。定义一个是用来存放元素的队列,再定义一个辅助的队列。两个队列的功能需要不停的更换。即现在queue1用来存放元素,但进行完某操作后,queue1可能就用了作为辅助了。
public class MyStack<E> {
/*存放元素的队列*/
private Queue<E> queue1 = new LinkedList<>();
/*辅助队列*/
private Queue<E> queue2 = new LinkedList<>();
/**
* 压栈(将元素e 压入栈顶)
*/
public void push(E e) {
queue1.offer(e);
}
/**
* 弹栈(移除并返回栈顶元素)
*
* @return
*/
public E pop() {
for (int i = 0; i < queue1.size() - 1; i++) {
queue2.offer(queue1.poll());
}
E lastE = queue1.poll();
Queue<E> temp = queue1;
queue1 = queue2;
queue2 = temp;
return lastE;
}
/**
* 获取栈顶元素
*
* @return
*/
public E peek() {
for (int i = 0; i < queue1.size() - 1; i++) {
queue2.offer(queue1.poll());
}
E lastE = queue1.poll();
queue2.offer(lastE);
Queue<E> temp = queue1;
queue2 = queue1;
queue1 = temp;
return lastE;
}
/**
* 判断栈内是否有元素
*
* @return
*/
public boolean isEmpty() {
return queue1.isEmpty() && queue2.isEmpty();
}
}
五、Java实现栈
(1)方式一:数组的方式实现:
public class ArrayStack<E> {
/*默认初始大小*/
private final int DEFAULT_SIZE = 10;
private Object[] elementArray;
private int usedSize;
public ArrayStack() {
elementArray = new Object[DEFAULT_SIZE];
}
/**
* 压栈
*
* @param e
*/
public E push(E e) {
if (isFull()) {
elementArray = Arrays.copyOf(elementArray, 2 * elementArray.length);
}
elementArray[usedSize] = e;
usedSize++;
return e;
}
/**
* 弹栈
*
* @return
*/
public E pop() {
if (usedSize == 0) throw new EmptyStackException();
E topE = (E) elementArray[usedSize - 1];
usedSize--;
elementArray[usedSize] = null;
return topE;
}
/**
* 获取栈顶元素
*/
public E peek() {
if (usedSize == 0) throw new EmptyStackException();
return (E) elementArray[usedSize - 1];
}
/**
* 数组是否已满
*
* @return
*/
private boolean isFull() {
return usedSize == elementArray.length;
}
/**
* 栈中是否有元素
*
* @return
*/
public boolean isEmpty() {
return usedSize == 0;
}
}
(2)方式二:链表的方式实现:
public class LinkStack<E> {
private Node<E> head;
/**
* 压栈
*
* @param e
* @return
*/
public E push(E e) {
Node<E> node = new Node<>(e);
node.next = head;
head = node;
return e;
}
/**
* 弹栈
*
* @return
*/
public E pop() {
if (head == null) throw new EmptyStackException();
E val = head.val;
Node<E> oldHead = head;
head = head.next;
oldHead.next = null;
return val;
}
/**
* 获取栈顶元素
*
* @return
*/
public E peek() {
if (head == null) throw new EmptyStackException();
return head.val;
}
/**
* 获取栈中元素的个数
*
* @return
*/
public int size() {
if (head == null) return 0;
Node<E> temp = head;
int size = 0;
while (temp != null) {
size++;
temp = temp.next;
}
return size;
}
/**
* 栈中是否有元素
*
* @return
*/
public boolean isEmpty() {
return head == null;
}
public static class Node<E> {
public E val;
public Node<E> next;
public Node(E val) {
this.val = val;
}
}
}