双向链表和单向链表相比更加灵活,它的每一个元素除了本身的值以为拥有两个指针,分别指向上一个和下一个节点。维护成本上要高于单向链表。链表的大部分操作依赖于遍历,这一方面双向链表会效率会好一些,可以根据查询下标的位置从而选择从链表头开始遍历还是从链表尾开始遍历。
package com.dfsn.cloud.eureka;
public class BothwayLinkedList<T> {
// 头节点
private Node first;
// 尾节点
private Node last;
// 元素个数
private int size = 0;
// 增加元素
public void add(T t) {
if (first == null) {
Node newNode = new Node(t, null, null);
first = newNode;
last = newNode;
} else {
Node newLast = new Node(t, null, last);
last.next = newLast;
last = newLast;
}
size++;
}
// 返回元素个数
public int size() {
return size;
}
// 遍历链表
public void show() {
if (first == null) {
throw new RuntimeException("链表为空");
} else {
Node temp = first;
while (true) {
System.out.println(temp);
if (temp.next == null) {
break;
}
temp = temp.next;
}
}
}
// 根据下标获取节点
public T get(int index) {
return get(index, "").item;
}
private Node get(int index, String s) {
if (first == null) {
throw new RuntimeException("链表为空,没有对应节点");
} else if (index >= size) {
throw new RuntimeException("链表长度为:" + size + ",index为" + (size - 1));
} else if (index < 0) {
throw new RuntimeException("下标不能<0");
} else {
int avg = size / 2;
if (index < avg) {
Node temp = first;
for (int i = 0; i < index; i++) {
temp = temp.next;
}
return temp;
} else {
Node temp = last;
for (int i = size - 1; i > index; i--) {
temp = temp.prev;
}
return temp;
}
}
}
// 在指定位置插入
public void add(int index, T t) {
if (index > size) {
throw new RuntimeException("链表长度为:" + size + ",index为" + size);
} else if (index < 0) {
throw new RuntimeException("下标不能<0");
} else if (index == 0) {
Node newNode = new Node(t, first, null);
newNode.next = first;
first = newNode;
} else if (index == size) {
Node newNode = new Node(t, null, last);
last.next = newNode;
last = newNode;
} else {
// 原来位置的node
Node node = get(index, "");
Node newNode = new Node(t, node, node.prev);
node.prev.next = newNode;
node.prev = newNode;
}
size++;
}
// 更改指定位置的元素
public void set(int index, T t) {
if (index >= size) {
throw new RuntimeException("链表长度为:" + size + ",index为" + (size - 1));
} else if (index < 0) {
throw new RuntimeException("下标不能<0");
} else {
Node node = get(index, "");
node.item = t;
}
}
// 删除指定位置的元素
public void remove(int index) {
if (index >= size) {
throw new RuntimeException("链表长度为:" + size + ",index为" + (size - 1));
} else if (index < 0) {
throw new RuntimeException("下标不能<0");
} else if (index == 0) {
first = first.next;
first.prev = null;
} else if (index == size - 1) {
last = last.prev;
last.next = null;
} else {
Node node = get(index, "");
Node next = node.next;
Node prev = node.prev;
prev.next = next;
next.prev = prev;
}
size--;
}
// 返回头节点
public T getFirst() {
return first.item;
}
// 返回尾节点
public T getLasts() {
return last.item;
}
// 节点对象
class Node {
private T item;
private Node next;
private Node prev;
public Node(T item, Node next, Node prev) {
this.item = item;
this.next = next;
this.prev = prev;
}
@Override
public String toString() {
return "Node [item=" + item + "]";
}
}
}
View Code