您的位置:首页 > 理论基础 > 数据结构算法

java 数据结构 LinkedList的基本实现

2018-01-12 14:28 686 查看

我用图表示每一个操作:

初始化操作(即new LinkedList()后的情况)



新增



删除



代码:

/**
* LinkedList implement
*/
public class MyLinkedList<T> implements Iterable<T> {

/**
* 头节点
*/
private Node<T> first;

/**
* 尾节点
*/
private Node<T> end;

/**
* 元素的数量
*/
private int theSize;

public MyLinkedList() {

/**
* 构造方法中将头尾节点连接起来
* 以下三句代码就是连接的代码
* 第一句将头节点实例化
* 第二句将尾节点实例化,并且把尾节点的prev指向头节点
* 第三局将头结点的next指向尾节点
*/
first = new Node(null, null, null);
end = new Node(null, first, null);
first.next = end;
/**
* size初始化
*/
theSize = 0;
}

@Override
public Iterator<T> iterator() {
return new MyIterator();
}

private class MyIterator<T> implements Iterator<T> {

/**
* 代表当前指向的节点
*/
private Node current;

public MyIterator() {
/**
* 构造方法把current指向第一个节点(即头结点的下一个节点)
* 因为头尾节点是不计算在元素内的
* 比如一个3个元素,即size==3的linkedList,实际有5个节点,因为多了头尾节点
*/
current = first.next;
}

@Override
public boolean hasNext() {
/**
* 判断是否有下一个节点
* 当current指向了尾节点时,说明没有下一个节点了
*/
return current != end;
}

@Override
public T next() {
/**
* 获取当前节点内的元素
*/
T element = (T) current.element;
/**
* 变化current的值为下一个节点
*/
current = current.next;
return element;
}

@Override
public void remove() {
/**
* 调用MyLinkedList内部的remove方法(current.prev的原因是我们每次在调了iterator.next()方法获取元素后,current实际已经指向了下一个节点,要想删除当前的元素,实际是删除current的前一个节点内的元素,即current.prev)
*/
MyLinkedList.this.remove(current.prev);
}
}

/**
* 这个类代表一个节点
* next代表这个节点连接的下一个节点
* prev代表上一个节点
* element是这个节点的元素
*
* @param <T>
*/
private static class Node<T> {

private Node next;

private Node prev;

private T element;

public Node() {
}

public Node(Node next, Node prev, T element) {
this.next = next;
this.prev = prev;
this.element = element;
}
}

public T get(int index) {
Node node;
node = getNode(index);
return (T) node.element;
}

/**
* 添加一个元素
*
* @param t
* @return
*/
public boolean add(T t) {
return add(t, theSize);
}

public boolean add(T t, int index) {
/**
*首先获取指定索引的节点
*/
Node old = getNode(index);
/**
* 我们新增一个节点,把新节点的next指向老节点,prev指向老节点的上一个节点
* 然后分别把新节点的上一个节点的next和下一个节点的prev都指向新节点
*/
Node newNode = new Node(old, old.prev, t);

newNode.prev.next = newNode.next.prev = newNode;

theSize++;
return true;
}

/**
* 获取指定索引的节点
*
* @param index
* @return
*/
public Node getNode(int index) {
if (theSize < index) {
throw new RuntimeException();
}
if (index == 0) {
return first.next;
}

/**
* 判断索引是在元素数量/2后的前半段还是后半段
*/
Node node;
if (theSize / index <= 2) {
node = end;
// 在右边,则从尾节点开始遍历
for (int i = index; i < theSize; i++) {
node = node.prev;
}
} else {
node = first;
// 在左边,则从头节点开始遍历
for (int i = 0; i <= index; i++) {
node = node.next;
}
}
return node;
}

public T remove(int index) {
Node node = getNode(index);
T remove = (T) remove(node);
return remove;
}

private T remove(Node<T> node) {
/**
* 删除即是把需要删除元素所在节点的上一个节点指向该节点的下一个节点(即绕过该节点)
*/
node.prev.next = node.next;
node.next.prev = node.prev;
T element = node.element;
node = null;
theSize--;
return element;
}

public int indexOf(T t) {
Node node = first;
for (int i = 0; i < theSize; i++) {
node = node.next;
T element = (T) node.element;
if (t == element) {
return i;
}
}
return -1;
}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息