栈
前面已经讲解过栈是什么,也用顺序存储的方式实现了栈,今天学习了链表,我们就用链式存储来实现一下栈
栈就是规定在一端进行插入和删除的线性表,而用链式存储实现栈,是在头部进行操作还是在尾部进行操作呢?
那我们还是来看一下头部插入和尾部插入的动画
看完这两个我们发现头插和尾插的时间复杂度都是O(1),可是我们想一下,删除一样吗,你把这两个动图倒着看,会发现头部删除我们只需要删除头指针的下一个,可是尾部删除的时候,我们必须遍历整个链表,找到尾指针的前面的那个结点,才能删除尾部元素,那时间复杂度可就是O(n)了啊,所以。。。。。。。。。总结一下,我们最后选用把链表的尾部当作栈底,头部当作栈头。
先看一下类图:
因为栈的实现依赖于线性表,所以很简单,代码实现如下:
package com.lfz.链表;
import com.lfz.栈.Stack;
public class LinkedStack<E> implements Stack<E> {
private LinkedList<E> list ;
public LinkedStack() {
list = new LinkedList<E>();
}
@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 void clear() {
list.clear();
}
@Override
public String toString() {
StringBuilder sb =new StringBuilder();
sb.append("LinkedStack: size="+getSize()+"\n");
if(isEmpty()) {
sb.append("[]");
}else {
sb.append('[');
for(int i=0;i<getSize();i++) {
sb.append(list.get(i));
if(i!=getSize()-1) {
sb.append(',');
} else {
sb.append(']');
}
}
}
return sb.toString();
}
@SuppressWarnings("unchecked")
@Override
public boolean equals(Object obj) {
if(obj == null) {
return false;
}
if(obj == this) {
return true;
}
if(obj instanceof LinkedStack) {
LinkedStack<E> stack = (LinkedStack<E>) obj;
return list.equals(stack.list);
}
return false;
}
}
队列
说完栈,再来说一下队列,前面我们也用顺序存储的方式实现了队列,接下来,也用链式存储实现一下队列。
队列就是只允许在一端进行插入操作,而在另一端进行删除操作的线性表,而用链式存储实现队列,是在头部进行插入/删除,还是在尾部进行插入/删除呢?
上面我们已经看过了头部和尾部的插入和删除的动图,那么我们现在来总结一下:
头部进行插入的时间复杂度 O(1)
头部进行删除的时间复杂度 O(1)
尾部进行插入的时间复杂度 O(1)
尾部进行删除的时间复杂度 O(n)
所以,我们在实现队列的时候最优的选的就是在尾部进行插入,头部进行删除
类图如下:
队列的实现也是依赖于线性表,所以也很简单,代码实现如下:
package com.lfz.链表;
import com.lfz.队列.Queue;
public class LinkedQueue<E> implements Queue<E> {
private LinkedList<E> list;
public LinkedQueue() {
list = new LinkedList<E>();
}
@Override
public int getSize() {
return list.getSize();
}
@Override
public boolean isEmpty() {
return list.isEmpty();
}
@Override
public void clear() {
list.clear();
}
@Override
public void enqueue(E e) {
list.addLast(e);
}
@Override
public E dequeue() {
return list.removeFirst();
}
@Override
public E getFront() {
return list.getFirst();
}
@Override
public E getRear() {
return list.getLast();
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("LinkedQueue: size="+getSize()+"\n");
if(isEmpty()) {
sb.append("[]");
}else {
sb.append('[');
for(int i=0;i<getSize();i++) {
sb.append(list.get(i));
if(i!=getSize()-1) {
sb.append(',');
} else {
sb.append(']');
}
}
}
return sb.toString();
}
@SuppressWarnings("unchecked")
@Override
public boolean equals(Object obj) {
if(obj == null) {
return false;
}
if(obj == this) {
return true;
}
if(obj instanceof LinkedQueue) {
LinkedQueue<E> stack = (LinkedQueue<E>) obj;
return list.equals(stack.list);
}
return false;
}
}
好了,栈和队列的链式存储结构就到这了,大家看完记得关注我哦,后面的会更加精彩的???