import java.util.NoSuchElementException;
public class LinkedListTest<E> {
int size=0;
//指向第一个结点的指针
Node<E> first;
//指向最后一个结点的指针
Node<E> last;
public LinkedListTest() {
}
//往首结点前面添加元素,先让first指针指向当前结点,如果首结点为null,说明这个链表是空的,当前这个结点就是首结点,也是尾结点,让last指针也指向它,否则,旧的首结点的prev他应该只想当前节点
public void linkFirst(E e) {
Node<E> f=first;//先定义一个指针指向首结点
//这个是新的首结点,将它的next指向旧首结点的指针
Node<E> newNode=new Node<>(null,e,f);
first=newNode;//指针指向当前的新结点
if(f==null)//说明链表还是空的,那首尾指针都应该是当前的结点
last=newNode;
else //将旧的头结点和新的头结点联系起来
f.prev=newNode;
size++;
}
//添加新的尾结点,先让last指针指向当前结点,如果尾结点为null,则说明当前链表为空,那么让first指针指向当前结点,否则,原来的尾结点的next应该指向当前结点
public void linkLast(E e) {
Node<E> l=last;
//将这个新结点的prev指向旧尾结点的指针
Node<E> newNode=new Node<>(l,e,null);
last=newNode;
//如果尾结点是null,说明连表示空的,就把首结点的指针也指向当前元素
if(l==null)
first=newNode;
//否则旧尾指针的next指向新尾指针
else l.next=newNode;
size++;
}
//向succ结点前面添加一个结点,先得到succ的前驱结点,如果前驱结点为null,相当于是往头结点前添加元素,就让first指针指向当前节点,否则,secc前驱结点的next指针应该指向当前节点
public void linkBefore(E e,Node<E> succ) {
Node<E> pred=succ.prev;
//当前结点的prev指针指向pred,next指针指向succ
Node<E> newNode=new Node<>(pred,e,succ);
succ.prev=newNode;
//如果succ就是首结点,那newNode就会变成新的首结点,就需要将first指针指向newNode
if (pred==null)
first=newNode;
//如果pred存在,则将他的next指向newNode
else pred.next=newNode;
size++;
}
//获取链表首结点的内容
public E getFirst() {
Node<E> f=first;
if(f==null)
throw new NoSuchElementException();
return f.item;
}
//获取链表尾结点的内容
public E getLast() {
Node<E> l=last;
if(l==null)
throw new NoSuchElementException();
return l.item;
}
public E removeFirst() {
Node<E> f=first;
if(f==null)
throw new NoSuchElementException();
return unlinkFirst(f);
}
public E removeLast() {
Node<E> l=last;
if(l==null)
throw new NoSuchElementException();
return unlinkLast(l);
}
//删除首结点,如果正常情况下,删除首结点以后由首结点的下一个来当首结点,需要将下一个首结点的prev置为null,如果首结点没有下一个元素,则说明这个链表空了,last置为null
private E unlinkFirst(Node<E> f) {
//先拿到首结点的元素值
E element=f.item;
Node<E> next=f.next;
f.item=null;
f.next=null;
//新的首结点就是f的next
first=next;
//如果整个链表中只有一个f结点,那么现在last指针也应该是空的
if(next==null)
last=null;
//next结点就是首结点,next的prev就是空
else next.prev=null;
size--;
return element;
}
//删除尾结点,正常情况下来说,删除尾结点就需要尾结点的前一个结点作为新的尾结点,如果尾结点不存在前驱,即链表中只有要删除的这个结点的话,那么就可以直接将fist指针置空,表示整个链表中没有元素了,
public E unlinkLast(Node<E> l) {
E element=l.item;
//新的尾结点
Node<E> prev=l.prev;
l.item=null;
l.prev=null;
last=l;
//如果l本来就是链表中的唯一一个结点,l删除后,first也应该置为空
if(prev==null)
first=null;
//否则,尾结点的next应该是空
else prev.next=null;
size--;
return element;
}
//删除x结点,如果x是首结点,就需要让首结点的下一个来作为新的首结点,所以first指针应该只想x的下一个结点,如果x是尾结点,就需要让尾结点的前一个来作为新的尾结点,所以last指针应该指向的是x的前驱
public E unlink(Node<E> x) {
E element=x.item;
Node<E> next=x.next;
Node<E> prev=x.prev;
//如果X是首结点,那么first指针应该指向x的next
if(prev==null)
first=next;
//否则,x.prev.next与x.next相连,
else {
prev.next=next;
x.prev=null;
}
//如果x是尾结点
if(next==null)
last=prev;
else {
next.prev=prev;
x.next=null;
}
x.item=null;
size--;
return element;
}
public void addFirst( E e) {
linkFirst(e);
}
public void addLast(E e) {
linkLast(e);
}
public boolean contains(Object o) {
return indexOf(o)!=-1;
}
public int indexOf(Object o) {
int index=0;
if(o==null) {
for(Node<E> x=first;x!=null;x=x.next) {
if(x.item==null)
return index;
index++;
}
}
else {
for(Node<E> x=first;x!=null;x=x.next) {
if(o.equals(x.item))
return index;
index++;
}
}
return -1;
}
public int size() {
return size;
}
public boolean add(E e) {
linkLast(e);
return true;
}
//根据元素值删除结点
public boolean remove(Object o) {
if(o==null) {
for(Node<E> x=first;x!=null;x=x.next) {
if(x.item==null) {
unlink(x);
return true;
}
}
}
else {
for(Node<E> x=first;x!=null;x=x.next) {
if(o.equals(x.item)) {
unlink(x);
return true;
}
}
}
return false;
}
public E get(int index) {
checkElementIndex(index);
return node(index).item;
}
//将index对应的元素值改成element
public E set(int index ,E element) {
checkElementIndex(index);
Node<E> x=node(index);
E oldVal=x.item;
x.item=element;
return oldVal;
}
//往对应下标中添加元素
public void add(int index,E element) {
checkElementIndex(index);
//直接往尾结点添加元素
if(index==size)
linkLast(element);
else {
//向index的结点前添加一个element结点
linkBefore(element,node(index));
}
}
//根据元素下标删除结点
public E remove(int index) {
checkElementIndex(index);
return unlink(node(index));
}
//返回尾结点的元素值
public E peek() {
Node<E> f=last;
return (f==null)?null:f.item;
}
//删除链表头结点
public E poll() {
Node<E> f=first;
return (f==null)?null:unlinkFirst(f);
}
public boolean offer(E e) {
return add((e));
}
public boolean offerFirst(E e) {
addFirst(e);
return true;
}
public boolean offerLast(E e) {
addLast(e);
return true;
}
public E peekFirst() {
Node<E> f=first;
return (f==null)?null:f.item;
}
public E peekLast() {
Node<E> l=last;
return (l==null)?null:l.item;
}
public E pollFirst() {
Node<E> f=first;
return (f==null)?null:unlinkFirst(f);
}
public E pollLast() {
Node<E> l=last;
return (l==null)?null:unlinkLast(l);
}
//添加新的头结点
public void push(E e) {
addFirst(e);
}
//得到链表的首结点
public E pop() {
return removeFirst();
}
//根据下标获取到链表元素
Node<E> node(int index) {
//判断index的大小然后决定是从前往后找还是从后往前找
if(index<(size>>1)) {
Node<E> x=first;
for(int i=0;i<index;i++)
x=x.next;
return x;
}
else {
Node<E> x=last;
for(int i=size-1;i>index;i--)
x=x.prev;
return x;
}
}
public void checkElementIndex(int index) {
if(!isElementIndex(index))
throw new IndexOutOfBoundsException();
}
private boolean isElementIndex(int index) {
return index>=0&&index<size;
}
private static class Node<E> {
E item;
Node<E> next;
Node<E> prev;
Node(Node<E> prev,E element,Node<E> next) {
this.item=element;
this.prev=prev;
this.next=next;
}
}
}
LinkedList底层源码的简单实现(常用方法)
于 2022-06-05 15:09:02 首次发布