简单手写一个双向循环链表
接口
public interface List<E> {
static final int ELEMENT_NOT_FOUND = -1;
//添加数据
void add(E element);
//插入元素到指定位置
void add(int index, E element);
//清除所有的元素
void clear();
//删除单个数据 通过动态数组的下标去操作
E remove(int index);
//通过下标去修改某一个元素
E set(int index, E element);
//通过元素的下标区查找某一个元素
E get(int index);
//查看元素的位置
int indexOf(E element);
//查看动态数组的长度
int size();
//查看元素是否为空
boolean isEmpty();
//查看是否包含某一个元素
boolean contains(E element);
}
父类
@SuppressWarnings("ALL")
public abstract class AbstractList<E> implements List<E> {
protected int size;
/**
* 元素的数量
*
* @return
*/
public int size() {
return size;
}
/**
* 是否为空
*
* @return
*/
public boolean isEmpty() {
return size == 0;
}
/**
* 是否包含某个元素
*
* @param element
* @return
*/
public boolean contains(E element) {
return indexOf(element) != ELEMENT_NOT_FOUND;
}
/**
* 添加元素到尾部
*
* @param element
*/
public void add(E element) {
add(size, element);
}
protected void outOfBounds(int index) {
throw new IndexOutOfBoundsException("Index:" + index + ", Size:" + size);
}
protected void rangeCheck(int index) {
if (index < 0 || index >= size) {
outOfBounds(index);
}
}
protected void rangeCheckForAdd(int index) {
if (index < 0 || index > size) {
outOfBounds(index);
}
}
}
双向循环链表
public class CircleLinkedList<E> extends AbstractList<E> {
private Node<E> first;
private Node<E> last;
//创建一个内部类Node 里面两个参数 元素和下一个元素的地址
private static class Node<E> {
E element;
Node<E> next;
Node<E> prev;
public Node() {
}
public Node(Node<E> prve, E element, Node<E> next) {
this.element = element;
this.next = next;
this.prev = prve;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
if (prev != null) {
sb.append(prev.element);
} else {
sb.append("null");
}
sb.append("_").append(element).append("_");
if (next != null) {
sb.append(next.element);
} else {
sb.append("null");
}
return sb.toString();
}
}
//创建一个方法 传入索引 返回一个节点
private Node<E> node(int index) {
rangeCheck(index);
if (index < (size >> 1)) {
Node<E> node = first;
for (int i = 0; i < index; i++) {
node = node.next;
}
return node;
} else {
Node<E> node = last;
for (int i = size - 1; i > index; i--) {
node = node.prev;
}
return node;
}
}
@Override
public void add(int index, E element) {
rangeCheckForAdd(index);
// size == 0
// index == 0
if (index == size) { // 往最后面添加元素
Node<E> oldLast = last;
last = new Node<>(oldLast, element, first);
if (oldLast == null) { // 这是链表添加的第一个元素
first = last;
//双向循环链表 添加的第一个节点 自己指向自己
first.next = first;
first.prev = first;
} else {
oldLast.next = last;
first.prev = last;
}
} else {
Node<E> next = node(index);
Node<E> prev = next.prev;
Node<E> node = new Node<>(prev, element, next);
next.prev = node;
prev.next = node;
if (next == first) { // index == 0
first = node;
}
}
size++;
}
@Override
public void clear() {
size = 0;
//只需要把第一个节点的first断开即可
first = null;
last = null;
}
@Override
public E remove(int index) {
rangeCheck(index);
Node<E> node = first;
if (size == 1) {
first = null;
last = null;
} else {
node = node(index);
Node<E> prve = node.prev;
Node<E> next = node.next;
prve.next = next;
if (index == 0) {//index == 0
first = next;
}
next.prev = prve;
if (node == last) {//index == size - 1
last = prve;
}
}
size--;
return node.element;
}
@Override
public E set(int index, E element) {
Node<E> node = node(index);
E oldElement = node.element;
node(index).element = element;
return oldElement;
}
@Override
public E get(int index) {
return node(index).element;
}
@Override
public int indexOf(E element) {
Node<E> node = first;
if (element == null) { // 1
for (int i = 0; i < size; i++) {
if (node.element == null) return i;
node = first.next;
}
} else {
for (int i = 0; i < size; i++) {
if (element.equals(node.element)) return i; // n
node = first.next;
}
}
return ELEMENT_NOT_FOUND;
}
@Override
public String toString() {
StringBuilder string = new StringBuilder();
string.append("size=").append(size).append(", [");
Node<E> node = first;
for (int i = 0; i < size; i++) {
if (i != 0) {
string.append(",");
}
string.append(node);
node = node.next;
}
string.append("]");
return string.toString();
}
}
测试
public class Test {
public static void main(String[] args) {
List<String> list = new CircleLinkedList<>();
//list.remove(0);
list.add("aaa");
list.add("aab");
list.add("aaa");
System.out.println(list);//size=3, [aaa, aab, aaa]
System.out.println(list.isEmpty());//false
list.add(0, "aaa1");
System.out.println(list);//size=4, [aaa1, aaa, aab, aaa]
list.add(2, "aaa2");
System.out.println(list);//size=5, [aaa1, aaa, aaa2, aab, aaa]
list.remove(2);
System.out.println(list);//size=4, [aaa1, aaa, aab, aaa]
list.clear();
System.out.println(list);//size=0, []
}
}
测试结果:
size=3, [aaa_aaa_aab,aaa_aab_aaa,aab_aaa_aaa]
false
size=4, [aaa_aaa1_aaa,aaa1_aaa_aab,aaa_aab_aaa,aab_aaa_aaa1]
size=5, [aaa_aaa1_aaa,aaa1_aaa_aaa2,aaa_aaa2_aab,aaa2_aab_aaa,aab_aaa_aaa1]
size=4, [aaa_aaa1_aaa,aaa1_aaa_aab,aaa_aab_aaa,aab_aaa_aaa1]
size=0, []
总结
实现思路和双向链表大同小异,改变的主要是添加和删除方法中的对头部(first)的处理。