双向链表中,除了一个保存值的 val,还有一个额外引用字段保存前一个节点,一个额外引用字段保存后一个节点。
节点结构
private class DoubleLinkedNode {
private int val;
private DoubleLinkedNode prev;
private DoubleLinkedNode next;
public DoubleLinkedNode(int val) {
this.val = val;
}
public int getVal() {
return val;
}
}
大多数情况下,使用头节点来表示整个链表。
操作
访问
无法随机访问单链表的元素。如果要遍历第 i 个元素,必须逐个遍历。
找到需要访问的节点,返回 val
public int get(int index) {
if (index < 0 || index >= size) {
return -1;
}
DoubleLinkedNode temp = head.next;
for (int i = 0; i < index; i++) {
temp = temp.next;
}
return temp.getVal();
}
添加
头插法(逆序)
由于尾节点的存在,不需要判断 null
public void addAtHead(int val) {
DoubleLinkedNode pred = head;
DoubleLinkedNode next = pred.next;
DoubleLinkedNode curr = new DoubleLinkedNode(val);
curr.prev = pred;
curr.next = next;
pred.next = curr;
next.prev = curr;
size++;
}
尾插法(顺序)
由于需要保存插入位置的原始前后节点,所以要遍历到 next.next != null。
public void addAtTail(int val) {
DoubleLinkedNode pred = head;
while (pred.next.next != null) {
pred = pred.next;
}
DoubleLinkedNode curr = new DoubleLinkedNode(val);
DoubleLinkedNode next = pred.next;
curr.prev = pred;
curr.next = next;
pred.next = curr;
next.prev = curr;
size++;
}
下标插入
遍历到插入节点的前一个节点,然后插入。
public void addAtIndex(int index, int val) {
if (index < 0 || index > size) {
return;
}
DoubleLinkedNode pred = head;
for (int i = 0; i < index; i++) {
pred = pred.next;
}
DoubleLinkedNode curr = new DoubleLinkedNode(val);
DoubleLinkedNode next = pred.next;
curr.prev = pred;
curr.next = next;
pred.next = curr;
next.prev = curr;
size++;
}
删除
需要保存删除节点的原前后节点,故
public void deleteAtIndex(int index) {
if (index < 0 || index >= size) {
return;
}
DoubleLinkedNode pred = head;
for (int i = 0; i < index; i++) {
pred = pred.next;
}
DoubleLinkedNode next = pred.next.next;
pred.next = next;
next.prev = pred;
size--;
}
设计双向链表
class MyLinkedList {
private int size;
private DoubleLinkedNode head;
private DoubleLinkedNode tail;
public MyLinkedList() {
head = new DoubleLinkedNode(0);
tail = new DoubleLinkedNode(0);
size = 0;
head.next = tail;
tail.prev = head;
}
public int get(int index) {
if (index < 0 || index >= size) {
return -1;
}
DoubleLinkedNode temp = head.next;
for (int i = 0; i < index; i++) {
temp = temp.next;
}
return temp.getVal();
}
public void addAtHead(int val) {
DoubleLinkedNode pred = head;
DoubleLinkedNode next = pred.next;
DoubleLinkedNode curr = new DoubleLinkedNode(val);
curr.prev = pred;
curr.next = next;
pred.next = curr;
next.prev = curr;
size++;
}
public void addAtTail(int val) {
DoubleLinkedNode pred = head;
while (pred.next.next != null) {
pred = pred.next;
}
DoubleLinkedNode curr = new DoubleLinkedNode(val);
DoubleLinkedNode next = pred.next;
curr.prev = pred;
curr.next = next;
pred.next = curr;
next.prev = curr;
size++;
}
public void addAtIndex(int index, int val) {
if (index < 0 || index > size) {
return;
}
DoubleLinkedNode pred = head;
for (int i = 0; i < index; i++) {
pred = pred.next;
}
DoubleLinkedNode curr = new DoubleLinkedNode(val);
DoubleLinkedNode next = pred.next;
curr.prev = pred;
curr.next = next;
pred.next = curr;
next.prev = curr;
size++;
}
public void deleteAtIndex(int index) {
if (index < 0 || index >= size) {
return;
}
DoubleLinkedNode pred = head;
for (int i = 0; i < index; i++) {
pred = pred.next;
}
DoubleLinkedNode next = pred.next.next;
pred.next = next;
next.prev = pred;
size--;
}
private class DoubleLinkedNode {
private int val;
private DoubleLinkedNode prev;
private DoubleLinkedNode next;
public DoubleLinkedNode(int val) {
this.val = val;
}
public int getVal() {
return val;
}
}
}
|