双链表与单链表的区别是,单链表只能沿着一个方向去查找,双链表可以沿着正向和反向进行查找。如下图所示。单链表的实现可以看我前面的博客
实现原理
在原来单链表的属性中会添加一个pre(存放前一个节点的地址),原有属性不变。
查找:和单链表的查找是完全一样的,只不过,通过反方向也可以进行查找
修改:和单链表的修改是一样的。
删除:删除有点特殊,单链表是将一个节点移除之后,将该节点的前一个节点的next指向该节点的下一个节点。但是双链表有点不同,除了将一个方向的指针移动之外,还要操作反方向的指针,即将删除节点的下一个节点的前驱指向删除节点的上一个节点,即完成删除。
添加:添加操作也有点不同,之前单链表是将节点添加到该链表的最后一个节点之后,将最后一个节点的next指向添加的节点即可。双链表也是将节点添加到最后一个节点之后,只不过还要将添加节点的前驱指向最后一个节点,实现双向链接。
实现代码
package cn.mrlij.linkedlist;
/**
* 双向链表的实现
*/
public class DoubleLinkedList {
public static void main(String[] args) {
DoubleLinkedListDemo s = new DoubleLinkedListDemo();
s.add(new HeroNode2(1,"张飞","小张"));
s.add(new HeroNode2(2,"刘备","小刘"));
s.add(new HeroNode2(3,"关羽","小关"));
// s.del(3); //删除
s.update(new HeroNode2(3,"曹操","小曹"));
s.list();
}
}
class DoubleLinkedListDemo{
//创建一个头结点,初始化数据,头结点不要动,不放具体的数据
private HeroNode2 head = new HeroNode2(0,"","");
public HeroNode2 getHead() {
return head;
}
//删除节点 与单链表不同的是,要删除节点.next.pre指向 要删除节点的前一个节点(排除删除最后一个节点的情况)
public void del(int no) {
if(head.next == null) {
System.out.println("链表为空!");
return;
}
HeroNode2 temp = head;
boolean flag = false;
while(true) {
if(temp.next == null) {
break;
}
if(temp.next.no == no) {
flag = true;
break;
}
temp = temp.next;
}
if(flag) {
temp.next = temp.next.next;
//需要做出判断,当删除的是最后一个节点,不作处理就会报空指针异常
if(temp.next != null){
temp.next.pre = temp;
}
// temp.pre.next = temp.next;
// if(temp.next!=null){
// temp.next.pre = temp.pre;
// }
// temp.pre.next = temp.next;
//
// //需要做出判断,当删除的是最后一个节点,就会报空指针异常
// if(temp.next!=null){
// temp.next.pre = temp.pre;
// }
}else {
System.out.println("该节点不存在!");
}
}
//修改节点内容
public void update(HeroNode2 node ) {
if(head.next == null) {
System.out.println("链表为空!");
return;
}
HeroNode2 temp = head.next;
boolean flag = false;
while(true) {
if(temp == null) {
break;
}
if(temp.no == node.no) {
flag = true;
break;
}
temp = temp.next;
}
if(flag) {
temp.name = node.name;
temp.nickname = node.nickname;
}else {
System.out.println("不存在该节点!");
}
}
//添加英雄
public void add(HeroNode2 node) {
//先找出最后的一个节点,把新加的节点放在最后一个节点的后面
HeroNode2 temp = head;
while(true) {
if(temp.next == null) {
break;
}
temp = temp.next;
}
temp.next = node;
//与单链表不同的是,添加的节点的前驱指向上一个节点
node.pre = temp;
}
//遍历链表,与单链表不同的是,可以从不同的方向遍历双向链表,即可以从前面遍历,也可以从后面遍历
public void list() {
HeroNode2 temp = head;
//首先判断链表是否为空
if(temp.next == null) {
System.out.println("链表为空!");
return;
}
while(true) {
if(temp.next == null) {
break;
}
System.out.println(temp.next);
temp = temp.next;
}
}
}
class HeroNode2{
public int no;//英雄编号
public String name;//人名
public String nickname;//绰号
public HeroNode2 next;//下一个节点
public HeroNode2 pre;//前一个节点
public HeroNode2(int no, String name, String nickname) {
this.no = no;
this.name = name;
this.nickname = nickname;
}
@Override
public String toString() {
return "HeroNode2 [no=" + no + ", name=" + name + ", nickname=" + nickname + "]";
}
}