双向链表
本双向链表的实现分别用first和last来表示头结点和尾结点,但此处的first和last即为第一个结点和最后一个结点本身,first和last的定义类似于一种指针的形式。没有对头结点和尾结点单独进行创建。
双向链表的构造
首先对双线链表类进行创建
public class DoublyLinkList {
private DoubleNode first;
private DoubleNode last;
public DoublyLinkList() {
first = null;
last = first;
}
}
然后创建内部节点类
class DoubleNode {
public int data; //数据域
public DoubleNode next; //指向下一个结点
public DoubleNode prev;
public DoubleNode(int data) {
this.data = data;
}
//打印结点的数据域
public void displayNode() {
System.out.print("{" + data + "} ");
}
}
对于双向链表的结点,需要分别定义next域以及prev域来分别指向其前驱结点和后继结点。
元素插入
首先对于头插法和尾插法进行实现,代码如下:(其中isEmpty()方法是对first是否为空进行判断)
// 头部插入
public void insertFirst(int data) {
DoubleNode newNode = new DoubleNode(data);
if (isEmpty()) {
last = newNode;
} else {
first.prev = newNode;
}
newNode.next = first;
first = newNode;
}
// 尾部插入
public void insertLast(int data) {
DoubleNode newNode = new DoubleNode(data);
if (isEmpty()) {
first = newNode;
} else {
last.next = newNode;
newNode.prev = last;
}
last = newNode;
}
当元素从指定key之后插入时,代码实现如下:
// 某个结点的后部插入
public void insertAfter(int key, int data) {
DoubleNode newNode = new DoubleNode(data);
DoubleNode curr = first;
while ((curr != null) && (curr.data != key)) {
curr = curr.next;
}
// 判断当前结点是否为空
if (curr == null) {
// 1.首结点是否为空
if (isEmpty()) {
last = newNode;
first = newNode;
} else {
// 2.找不到key值
last.next = newNode;
newNode.prev = last;
last = newNode;
}
} else {
// 当前结点不为空时,又有以下两种情况
// 1.找到的key对应的结点在最后
if (curr == last) {
newNode.next = null;
last = newNode;
} else {
// 2.在两个结点之间找到
newNode.next = curr.next;
curr.next.prev = newNode;
}
curr.next = newNode;
newNode.prev = curr;
}
}
元素删除
删除首个元素和删除末尾元素的方法如下:(这里要注意,删首个元素时,如果只有一个元素,需要用last去指向null,反之则是用first指向。否则下面first.next会报空指针异常)
// 删除首个元素
public DoubleNode deleteFirst() {
DoubleNode temp = first;
// 如果只有一个元素
if (first.next == null) {
// 将last指向null
last = null;
} else {
// 如果由两个及以上的元素
first.next.prev = null;
}
first = first.next;
return temp;
}
// 删除尾部元素
public DoubleNode deleteLast() {
DoubleNode temp = last;
if (first.next == null) {
// 如果只有一个元素
first = null;
} else {
// 如果有两个及两个以上的元素
last.prev.next = null;
}
last = last.prev;
return temp;
}
对于从中间某处元素的删除,则需要改动两处元素指向,并且判断情况。其中如果curr为first或者last时,需要像上述方法一样进行是否为单元素的判断,这里直接引用了上面的方法,否则可能会有空指针异常。
public DoubleNode deleteAfter(int key) {
DoubleNode curr = first;
while ((curr != null) && (curr.data != key)) {
curr = curr.next;
}
if (curr == null) {
return null;
} else {
// 如果curr是第一个结点
if (curr == first) {
deleteFirst();
} else if (curr == last) {
// 如果curr是最后一个结点
deleteLast();
} else {
curr.prev.next = curr.next;
curr.next.prev = curr.prev;
}
}
return curr;
}