LinkedList实现
本节给出LinkedList的实现,命名为MyLinkedList。采用普遍的双链表,与ArrayList相比,可以较快地进行插入和删除操作,只需要将元素的指针指向改变即可,实现常数次操作。保存该链表的首末段指针(引用),保证对头尾元素的访问为O(1),并且,如果已知访问元素的位置,就可以决定从哪个端点开始遍历,一定程度上补偿链表的访问速度问题,双端列表的简单结构如下图。
功能描述
- MyLinkedList包含链表两端,大小以及一些常用方法;
- Node类,用来描述链表节点,包含自身数据、指向下一个节点和上一个节点的指针,以及一些适当的构造方法;
- LinkedListIterator类,该类实现了Iterator接口,可以作为内部类或嵌套类在MyLinkedList内部实现,提供next(), hasNext(0和remove()方法实现。
代码实现
package com.yam.base;
import java.util.ConcurrentModificationException;
import java.util.Iterator;
import java.util.NoSuchElementException;
/**
* LinkedList简单实现
* @author: Ympery
* @date: 2017/3/13 15:00.
*/
public class MyLinkedList<AnyType> implements Iterable<AnyType> {
/**
* 链表长度
*/
private int theSize;
/**
* 用于标记链表自构造起,对其的操作次数,防止并发错误
*/
private int modCount = 0;
/**
* 整个链表的头结点
*/
private Node<AnyType> beginMarker;
/**
* 整个链表的尾节点
*/
private Node<AnyType> endMarker;
public MyLinkedList() { clear(); }
/**
* 清除链表,当链表为null时,只有头尾
*/
public void clear() {
beginMarker = new Node<>(null, null, null);
endMarker = new Node<>(null, beginMarker, null);
beginMarker.next = endMarker;
theSize = 0;
modCount++;
}
/**
* 返回长度
* @return
*/
public int size() { return theSize; }
/**
* 判断链表是否为空
* @return
*/
public boolean isEmpty() { return theSize == 0; }
/**
* 在链表末端添加值
* @param x
* @return
*/
public boolean add(AnyType x) {
add(size(), x);
return true;
}
/**
* 按索引位置添加值
* @param idx 位置
* @param x 添加的元素
*/
public void add(int idx, AnyType x) {
addBefore(getNode(idx), x);
}
/**
* 按索引位置获取节点值
* @param idx
* @return
*/
public AnyType get(int idx) {
return getNode(idx).data;
}
/**
* 按索引位置设置新值
* @param idx 索引
* @param newVal 值
* @return
*/
public AnyType set(int idx, AnyType newVal) {
Node<AnyType> p = getNode(idx);
AnyType oldVal = p.data;
p.data = newVal;
return oldVal;
}
/**
* 按索引位置删除值
* @param idx
* @return
*/
public AnyType remove(int idx) {
return remove(getNode(idx));
}
/**
* 删除指定节点
* @param p
* @return
*/
private AnyType remove(Node<AnyType> p) {
p.prev.next = p.next;
p.next.prev = p.prev;
theSize--;
modCount++;
return p.data;
}
/**
* 在节点前插入节点
* @param p 指定节点(在此节点之前插入新节点)
* @param x 要插入的节点的值
*/
private void addBefore(Node<AnyType> p, AnyType x) {
Node<AnyType> newNode = new Node<>(x, p.prev, p);
newNode.prev.next = newNode;
p.prev = newNode;
theSize++;
modCount++;
}
/**
* 按索引位置获取链表节点
* @param idx 索引位置
* @return
*/
private Node<AnyType> getNode(int idx) {
Node<AnyType> p;
if (0 > idx || idx > size())
throw new IndexOutOfBoundsException();
// 判断查询位置在链表的前半部分
if (size() / 2 > idx) {
p = beginMarker.next;
for (int i = 0; i < idx; i++)
p = p.next;
}
// 判断查询位置在链表的后半部分
else {
p = endMarker;
for (int i = size(); i > idx; i--)
p = p.prev;
}
return p;
}
public Iterator<AnyType> iterator() {
return new LinkedListIterator();
}
/**
* MyLinkedList的迭代器,使用内部类实现
*/
private class LinkedListIterator implements Iterator<AnyType> {
private Node<AnyType> current = beginMarker.next;
private int expectedModCount = modCount;
private boolean okToRemove = false;
@Override
public boolean hasNext() {
return current != endMarker;
}
@Override
public AnyType next() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
if (!hasNext())
throw new NoSuchElementException();
AnyType nextItem = current.data;
current = current.next;
okToRemove = true;
return nextItem;
}
@Override
public void remove() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
if (!okToRemove)
throw new IllegalStateException();
MyLinkedList.this.remove(current);
okToRemove = false;
expectedModCount++;
}
}
/**
* 链表节点
* @param <AnyType>
*/
private static class Node<AnyType> {
public Node(AnyType d, Node<AnyType> p, Node<AnyType> n) {
data = d;
prev = p;
next = n;
}
/**
* 当前节点数据
*/
public AnyType data;
/**
* 上一个节点的引用
*/
public Node<AnyType> prev;
/**
* 下一个节点引用
*/
public Node<AnyType> next;
}
/**
* 测试
* @param args
*/
public static void main(String[] args) {
MyLinkedList<Character> chLinkList = new MyLinkedList<>();
char c = 'a';
for (int i = 0; i < 20; i++)
chLinkList.add(c++);
for (char ch : chLinkList)
System.out.print(ch + " ");
System.out.println("删除之前");
chLinkList.remove(10);
for (char ch : chLinkList)
System.out.print(ch + " ");
System.out.println("删除之后");
Iterator iterator = chLinkList.iterator();
System.out.println("采用迭代器遍历");
while (iterator.hasNext())
System.out.print(iterator.next() + " ");
}
}