前言:前面几篇介绍了线性表的顺序和链式存储结构,其中链式存储结构为单向链表(即一个方向的有限长度、不循环的链表),对于单链表,由于每个节点只存储了向后的指针,到了尾部标识就停止了向后链的操作。也就是说只能向后走,如果走过了,就回不去了,还得重头开始遍历,所以就衍生出了循环链表
定义:将单链表中中断结点的指针端有空指针改为指向头结点,就使整个单链表形成一个环,这种头尾详解的单链表称为单循环链表,简称循环链表;
特性:
- 若链表为空,则头结点的next结点还是指向其本身,即head.next=head;
- 尾节点的next指针指向head结点,即头尾相连;
- 判断是否遍历了完,直接判断next==head即可;
- 由单链表变化的循环也成为单向循环链表;
- 循环链表的特点是无须增加存储量,仅对表的链接方式稍作改变,即可使得表处理更加方便灵活;
二、单向循环链表的实现
循环链表是在单链表(线性单链表)的基础上,将尾节点的next指向了head,所以基本的结构是类似的,所以下面,直接贴代码了;
public class LoopChain<T> { //尾结点直接引用 private Node<T> tail; //链长度 private Integer size; //初始化 LoopChain() { tail = new Node<T>(); tail.setNext(tail); } public Node<T> remove(Integer index) throws Exception { //获取该位置的上一个节点 Node<T> s = getNode(index - 1); //获取该位置节点的下一个节点 Node<T> next = getNode(index).getNext(); //将本节点的next节点放在本节点的前一个节点的next节点位置 s.setNext(next.getNext()); return next; } public void add(T t,Integer index) throws Exception { //获取该位置的上一个节点 Node<T> s = getNode(index - 1); //创建新节点 Node<T> p = new Node<>(); p.setObject(t); //将本节点的next节点放入新节点的next节点 p.setNext(s.getNext()); //将新节点放入本节点的next节点位置 s.setNext(p); } public T get(Integer index) throws Exception { return (T)getNode(index).getObject(); } private Node<T> getNode(Integer index) throws Exception { if (index > size || index < 0) throw new Exception("index outof length"); //取头节点 Node<T> p = tail.next; for (int i = 0; i < index; i++) p = p.getNext(); return p; } class Node<T> { private Object object; private Node next; public Object getObject() { return object; } public void setObject(Object object) { this.object = object; } public Node getNext() { return next; } public void setNext(Node next) { this.next = next; } } }
获取元素:
public T get(Integer index) throws Exception { return (T)getNode(index).getObject(); } private Node<T> getNode(Integer index) throws Exception { if (index > size || index < 0) throw new Exception("index outof length"); //取头节点 Node<T> p = tail.next; for (int i = 0; i < index; i++) p = p.getNext(); return p; }
插入元素:
public void add(T t,Integer index) throws Exception { //获取该位置的上一个节点 Node<T> s = getNode(index - 1); //创建新节点 Node<T> p = new Node<>(); //将本节点的next节点放入新节点的next节点 p.setNext(s.getNext()); //将新节点放入本节点的next节点位置 s.setNext(p); }
移除元素:
public Node<T> remove(Integer index) throws Exception { //获取该位置的上一个节点 Node<T> s = getNode(index - 1); //获取该位置节点的下一个节点 Node<T> next = getNode(index).getNext(); //将本节点的next节点放在本节点的前一个节点的next节点位置 s.setNext(next.getNext()); return next; }