双向有环链表意思是我们能通过当前节点可以保存上一个节点和下一个节点的信息,并且各个节点连接成一个环形,也就是说我们可以通过正向(next)遍历这个链表,也可以逆向(prev)遍历这个链表。
这样我们就可以完成无头双向有环链表的基本操作了。
class DLinkedNode {
public int val = 0;
public DLinkedNode prev = null;
public DLinkedNode next = null;
public DLinkedNode(int val) {
this.val = val;
}
}
public class DLinkedList {
private DLinkedNode head = null;
//创建傀儡节点
public DLinkedList() {
head = new DLinkedNode(-1);
head.prev = head;
head.next = head;
}
//加在第一个位置
public void addFirst(int data) {
DLinkedNode newNode = new DLinkedNode(data);
newNode.next = head.next;
newNode.prev = head;
head.next.prev = newNode;
head.next = newNode;
}
//加在最后一个位置
public void addLast(int data) {
DLinkedNode newNode = new DLinkedNode(data);
newNode.prev = head.prev;
newNode.next = head;
head.prev.next = newNode;
head.prev = newNode;
}
//任意位置插入
public void addIndex(int index, int data) {
DLinkedNode newNode = new DLinkedNode(data);
//获取到当前链表中Index位置的节点
DLinkedNode Node = head.next;
for (int i = 0; i < index; i++) {
Node = Node.next;
}
newNode.next = Node;
newNode.prev = Node.prev;
Node.prev.next = newNode;
Node.prev = newNode;
}
//删除第一次出现关键字key的节点
public void remove(int key) {
DLinkedNode node;
for (node = head.next;
node != head; node = node.next) {
if (node.val == key) {
break;
}
}
node.prev.next = node.next;
node.next.prev = node.prev;
}
//删除所有关键字为key的节点
public void removeAll(int key) {
DLinkedNode node = head.next;
while (node != head) {
if (node.val == key) {
node.prev.next = node.next;
node.next.prev = node.prev;
}
node = node.next;
}
}
//得到链表长度
public int size() {
int size = 0;
for (DLinkedNode node = head.next;
node != head; node = node.next) {
size++;
}
return size;
}
//清空链表
public void clearAll() {
DLinkedNode newHead = new DLinkedNode(-1);
newHead.next = newHead;
newHead.prev = newHead;
head = newHead;
}
public void disPlay() {
//正向
System.out.println("正向");
System.out.print("[");
for (DLinkedNode node = head.next; node != head; node = node.next) {
System.out.print(node.val);
if (node.next != head) {
System.out.print(",");
}
}
System.out.println("]");
//反向
System.out.println("反向");
System.out.print("[");
for (DLinkedNode node = head.prev; node != head; node = node.prev) {
System.out.print(node.val);
if (node.prev != head) {
System.out.print(",");
}
}
System.out.println("]");
}
}
下面是测试链表的代码
public class TestDLinkedList {
public static void main(String[] args) {
testAddFirst();
testAddLast();
testAddIndex();
testRemove();
testRemoveAll();
testSize();
testClearAll();
}
public static void testAddFirst() {
System.out.println("测试addFirst");
DLinkedList dLinkedList = new DLinkedList();
dLinkedList.addFirst(1);
dLinkedList.addFirst(2);
dLinkedList.addFirst(3);
dLinkedList.addFirst(4);
dLinkedList.addFirst(5);
dLinkedList.disPlay();
}
public static void testAddLast() {
System.out.println("测试addLast");
DLinkedList dLinkedList = new DLinkedList();
dLinkedList.addLast(1);
dLinkedList.addLast(2);
dLinkedList.addLast(3);
dLinkedList.addLast(4);
dLinkedList.addLast(5);
dLinkedList.disPlay();
}
public static void testAddIndex() {
System.out.println("测试addIndex,在2节点位置增加7");
DLinkedList dLinkedList = new DLinkedList();
dLinkedList.addLast(0);
dLinkedList.addLast(1);
dLinkedList.addLast(2);
dLinkedList.addLast(3);
dLinkedList.addLast(4);
dLinkedList.addLast(5);
dLinkedList.addIndex(2, 7);
dLinkedList.disPlay();
}
public static void testRemove() {
System.out.println("测试Remove,把第一次出现7的节点删除");
DLinkedList dLinkedList = new DLinkedList();
dLinkedList.addLast(0);
dLinkedList.addLast(1);
dLinkedList.addLast(2);
dLinkedList.addLast(3);
dLinkedList.addLast(4);
dLinkedList.addLast(5);
dLinkedList.addIndex(2, 7);
dLinkedList.addIndex(5, 7);
dLinkedList.disPlay();
dLinkedList.remove(7);
dLinkedList.disPlay();
}
public static void testRemoveAll() {
System.out.println("测试删除所有节点值为7的节点");
DLinkedList dLinkedList = new DLinkedList();
dLinkedList.addLast(0);
dLinkedList.addLast(1);
dLinkedList.addLast(2);
dLinkedList.addLast(3);
dLinkedList.addLast(4);
dLinkedList.addLast(5);
dLinkedList.addIndex(2, 7);
dLinkedList.addIndex(5, 7);
dLinkedList.disPlay();
dLinkedList.removeAll(7);
dLinkedList.disPlay();
}
public static void testSize() {
System.out.println("测试链表长度");
DLinkedList dLinkedList = new DLinkedList();
dLinkedList.addLast(0);
dLinkedList.addLast(1);
dLinkedList.addLast(2);
dLinkedList.addLast(3);
dLinkedList.addLast(4);
dLinkedList.addLast(5);
dLinkedList.addIndex(2, 7);
dLinkedList.addIndex(5, 7);
System.out.println("链表长度为:" + dLinkedList.size());
dLinkedList.disPlay();
dLinkedList.removeAll(7);
dLinkedList.disPlay();
}
public static void testClearAll() {
System.out.println("测试清空链表");
DLinkedList dLinkedList = new DLinkedList();
dLinkedList.addLast(0);
dLinkedList.addLast(1);
dLinkedList.addLast(2);
dLinkedList.disPlay();
dLinkedList.clearAll();
System.out.println("链表长度为:" + dLinkedList.size());
dLinkedList.disPlay();
}
}
运行效果如图: