链表(Java)二
上次咱们介绍了单链表(链表(一))
(本次关于查找添加以及删除的实现也使用上次在单链表里写的接口)
下面咱们介绍一下双链表。双链表比单链表在查询方面要快得多,但是它更加复杂,它包含了 size,记录链表元素个数,和伪头伪尾。
一、节点结构:
class ListNode{
int val;
//指向下一个节点
ListNode next;
// 与单链表的节点不同
// 指向下一个节点
ListNode prev;
public ListNode(){};
public ListNode(int val){
this.val =val;
}
}
双链表初始状态如下图:
咱们用代码表示一下:
public DoublyLinkedList(){
size=0;
head=new ListNode(0);
tail=new ListNode(0);
head.next=tail;
tail.prev=head;
}
二、双链表的添加操作:
(toAdd表示当前需要插入的新节点,以插入节点的值为5作为例子
ListNode toAdd=new ListNode(5);
pred表示当前要插入的新节点的上一个节点
succ表示当前要插入的新节点的下一个节点)
- 找到要插入节点的前驱节点(pred)和后继节点(succ)。
- 通过改变前驱结点和后继节点的链接关系添加元素。
2.
3.
4.
至此,新节点插入完成
代码表示如下:
ListNode toAdd = new ListNode(e);
toAdd.prev = pred;
toAdd.next = succ;
pred.next = toAdd;
succ.prev = toAdd;
三、双链表的删除操作:
- 找到要删除节点的前驱结点(pred)和后继节点(succ)。
- 通过改变前驱结点和后继节点的链接关系删除元素。
1.
至此,双链表的删除操作也完成啦
代码如下:
pred.next = succ;
succ.prev = pred;
四、双链表的查找操作
- 将index和size的一半进行比较,判断是从头开始寻找,还是从尾开始寻找。简而言之,哪里路径短就从哪里开始找。
操作如下:
1.当size为3,index为0时,通过if语句判断,从头开始查找比较快
2.当size为3,index为2时,通过if语句判断,从尾巴开始查找比较快
代码如下:
ListNode p=head;
if(index+1<size-index) {
for (int i = 0; i < index + 1; ++i) {
p = p.next;
}
} else{
p = tail;
for (int i = 0; i < size - index; ++i) {
p = p.prev;
}
}
return p.val;
以上就是双链表的添加,删除与查找
全部代码如下:
/**
* @program: testspring
* @description: 双链表
* @author: ErFeng_V
* @create: 2021-05-03 23:13
*/
public class DoublyLinkedList implements MyLinkedList {
private int size;
private ListNode head;
private ListNode tail;
public DoublyLinkedList(){
size=0;
head=new ListNode(0);
tail=new ListNode(0);
head.next=tail;
tail.prev=head;
}
@Override
public void addAtHead(int e) {
addAtIndex(0,e);
}
@Override
public void addAtTail(int e) {
addAtIndex(size,e);
}
@Override
public int get(int index) {
if(index<0 || index>=size){
return -1;
}
ListNode p=head;
if(index+1<size-index) {
for (int i = 0; i < index + 1; ++i) {
p = p.next;
}
} else{
p = tail;
for (int i = 0; i < size - index; ++i) {
p = p.prev;
}
}
return p.val;
}
@Override
public void addAtIndex(int index, int e) {
if (index > size) {
return;
}
//根据题意,当index小于0时,则在头部插入节点。
if (index < 0) {
index = 0;
}
ListNode pred, succ;
if (index < size - index) {
pred = head;
for(int i = 0; i < index; ++i) {
pred = pred.next;
}
succ = pred.next;
}
else {
succ = tail;
for (int i = 0; i < size - index; ++i) {
succ = succ.prev;
}
pred = succ.prev;
}
++size;
ListNode toAdd = new ListNode(e);
toAdd.prev = pred;
toAdd.next = succ;
pred.next = toAdd;
succ.prev = toAdd;
}
@Override
public void deleteAtIndex(int index) {
if (index < 0 || index >= size) {
return;
}
ListNode pred, succ;
if (index < size - index) {
pred = head;
for(int i = 0; i < index; ++i) {
pred = pred.next;
}
succ = pred.next.next;
}
else {
succ = tail;
for (int i = 0; i < size - index - 1; ++i) {
succ = succ.prev;
}
pred = succ.prev.prev;
}
--size;
pred.next = succ;
succ.prev = pred;
}
}
class ListNode{
int val;
ListNode next;
ListNode prev;
public ListNode(){};
public ListNode(int val){
this.val =val;
}
}