这次的两循环链表是基于上篇的两链表,不同的就是首尾相互指向,所以主要改动在add,remove方法上。
单向循环链表
package com.ldg.circle;
import java.util.IllegalFormatCodePointException;
import org.omg.PortableServer.ID_ASSIGNMENT_POLICY_ID;
import com.ldg.AbstractList;
@SuppressWarnings("unused")
//单向循环链表类
//相对与单链表只需要修改add remove部分 其他的通用
public class SingleCircleLinkedList<T> extends AbstractList<T> {
// 指的是首节点 由首节点指向链表
private Node<T> first;
// 声明节点类
@SuppressWarnings("hiding")
private class Node<T> {
T element;
Node<T> next;
public Node(T element, Node<T> next) {
this.element = element;
this.next = next;
}
}
/**
* 根据序号返回节点 从首节点一个个next
*
* @param index
* @return
*/
public Node<T> node(int index) {
// 判断序号是否越界
isOutSize(index);
Node<T> node = first;
for (int i = 0; i < index; i++) {
node = node.next;
}
return node;
}
/**
* 根据索引添加元素 返回原始值 注意index=0 index=size index=size-1的边界情况
*
*/
@Override
public T add(int index, T element) {
T old;
// 改成循环链表时修改if这部分,else可以继续使用.
//是不是index=0 添加
if (index == 0) {
//声明新节点
Node<T> node = new Node<T>(element, first);
//判断:新节点是不是第一个节点
if (first == null)
{
old = null;
first = node;
node.next = first;
} else {
old = first.element;
node(size - 1).next = node;
first = node;
}
} else {
Node<T> node = node(index - 1).next;
if (node == null) {
old = null;
} else {
old = node.element;
}
node(index - 1).next = new Node<T>(element, node(index - 1).next);
}
size++;
return old;
}
@Override
public void add(T element) {
add(size, element);
}
@Override
public T remove(int index) {
isOutSize(index);
T old;
//删除第一节点
if (index == 0)
{
old = first.element;
if (size == 1) {
first = null;
} else {
//最后一个节点指向第一个节点
node(size - 1).next = first.next;
//first指向第一个节点
first = first.next;
}
} else {
old = node(index).element;
node(index - 1).next = node(index - 1).next.next;
}
size--;
return old;
}
@Override
public T set(int index, T element) {
T old = node(index).element;
node(index).element = element;
return old;
}
@Override
public void clear() {
size = 0;
first = null;
}
@Override
public T get(int index) {
return node(index).element;
}
@Override
public int indexOf(T element) {
Node<T> node = first;
for (int i = 0; i < size; i++) {
if (node.element.equals(element)) {
return i;
}
node = node.next;
}
return ELEMENT_NOT_FOUND;
}
@Override
public String toString() {
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append("Size:" + size + " LinkedList[");
for (int i = 0; i < size; i++) {
if (i != 0) {
stringBuilder.append(",");
}
stringBuilder.append(node(i).element);
}
stringBuilder.append("]");
return stringBuilder.toString();
}
/***
* 反转链表
*
* @param head
* @return
*/
// public Node<T> reverseList(Node<T> head) {
//
// if (head == null || head.next == null)
// return head;
// // 与当前链表关联 这样才不会出现空指针
// first = reverseList(head.next);
// head.next.next = head;
// head.next = null;
//
// return first;
//
// }
// 判断是否为循坏链表
public boolean hasCycle(Node<T> head) {
if (head == null)
return false;
Node<T> slowListNode = head;
Node<T> fastListNode = head.next;
while (fastListNode != null && fastListNode.next != null) {
slowListNode = slowListNode.next;
fastListNode = fastListNode.next.next;
if (slowListNode == fastListNode) {
return true;
}
}
return false;
}
}
双向循环链表
package com.ldg.circle;
import java.util.IllegalFormatCodePointException;
import org.omg.PortableServer.ID_ASSIGNMENT_POLICY_ID;
import com.ldg.AbstractList;
@SuppressWarnings("unused")
//双向循环链表类
//相对于双向链表修改的地方还是 add 和 remove
public class CircleLinkedList<T> extends AbstractList<T> {
// 指的是首节点 由首节点指向链表
private Node<T> first;
// 尾节点
private Node<T> last;
// 声明节点类
@SuppressWarnings("hiding")
private class Node<T> {
T element;
// 后一个节点
Node<T> next;
// 前一个节点
Node<T> pre;
public Node(Node<T> pre, T element, Node<T> next) {
this.pre = pre;
this.element = element;
this.next = next;
}
}
/**
* 根据序号返回节点 分情况从头或者尾开始移动
*
* @param index
* @return
*/
public Node<T> node(int index) {
// 判断序号是否越界
isOutSize(index);
Node<T> node = null;
if (index < size >> 2) {
node = first;
for (int i = 0; i < index; i++) {
node = node.next;
}
} else {
node = last;
for (int i = size - 1; i > index; i--) {
node = node.pre;
}
}
return node;
}
/**
* 注意一下节点中两个指针的指向.不要漏忘 根据索引添加元素 返回原始值
* 注意index=0 index=size index=size-1的边界情况
*/
@Override
public T add(int index, T element) {
T old;
// 直接添加到链表最后面
if (index == size) {
old = null;
Node<T> pre = last;
Node<T> node = new Node<T>(pre, element, first);
last = node;
if (index == 0) // 当index=size=0;唯一的一个节点
{ //自己指向自己
first = node;
node.next=node;
node.pre=node;
} else {
//首尾相指
first.pre = node;
pre.next = node;
}
} else {
Node<T> next = node(index);
old = next.element;
Node<T> pre = node(index).pre;
Node<T> node = new Node<T>(pre, element, next);
if (index == 0)// index=0
{
first = node;
} else {
pre.next = node;
}
next.pre = node;
}
size++;
return old;
}
/**
* 添加
*/
@Override
public void add(T element) {
add(size, element);
}
/**
* 移除节点
* 条件判断具有对称性。
*/
@Override
public T remove(int index) {
isOutSize(index);
T old = null;
Node<T> next = node(index).next;
Node<T> pre = node(index).pre;
if (index == 0) // index=0的情况
{
first = next;
last.next=first;
} else {
pre.next = next;
}
if (index == size - 1) // index=size-1的情况;
{
last = pre;
first.pre=last;
} else {
next.pre = pre;
}
size--;
return old;
}
@Override
public T set(int index, T element) {
T old = node(index).element;
node(index).element = element;
return old;
}
// 如果不是被gc root对象指向的内存地址块会被java回收站机制回收。
// 就是没局部变量指向的对象。
@Override
public void clear() {
size = 0;
first = null;
last = null;
}
@Override
public T get(int index) {
return node(index).element;
}
@Override
public int indexOf(T element) {
Node<T> node = first;
for (int i = 0; i < size; i++) {
if (node.element.equals(element)) {
return i;
}
node = node.next;
}
return ELEMENT_NOT_FOUND;
}
// Stringbuilder的拼接
@Override
public String toString() {
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append("Size:" + size + " LinkedList[");
for (int i = 0; i < size; i++) {
if (i != 0) {
stringBuilder.append(",");
}
stringBuilder.append(node(i).element);
}
stringBuilder.append("]");
return stringBuilder.toString();
}
/***
* 反转链表
*
* @param head
* @return
*/
// public Node<T> reverseList(Node<T> head) {
//
// if (head == null || head.next == null)
// return head;
// // 与当前链表关联 这样才不会出现空指针
// first = reverseList(head.next);
// head.next.next = head;
// head.pre = head.next;
// last = head;
//
// return first;
//
// }
// 判断是否为循坏链表
public boolean hasCycle(Node<T> head) {
if (head == null)
return false;
Node<T> slowListNode = head;
Node<T> fastListNode = head.next;
while (fastListNode != null && fastListNode.next != null) {
slowListNode = slowListNode.next;
fastListNode = fastListNode.next.next;
if (slowListNode == fastListNode) {
return true;
}
}
return false;
}
}
外加一个检测是否为循环链表的小算法
// 判断是否为循坏链表
public boolean hasCycle(Node<T> head) {
if (head == null)
return false;
Node<T> slowListNode = head;
Node<T> fastListNode = head.next;
while (fastListNode != null && fastListNode.next != null) {
slowListNode = slowListNode.next;
fastListNode = fastListNode.next.next;
if (slowListNode == fastListNode) {
return true;
}
}
return false;
}
以上代码经测试都能够跑通。