双向链表
管理单向链表的缺点:
单向链表,查找方向只能是一个方向,二双向链表可以此案前或者先后查找
单向链表不能自我删除,需要开辅助节点,二双向链表则可以自我删除,所以前边单链表删除时总要找到temp,temp时待删除节点的前一个节点
双向链表的增删改查
遍历
思路——方法同单向链表,就是循环打印
代码如下
public void list() {
//判断链表是否为空
if(head.next == null) {
System.out.println("链表为空");
return;
}
HeroNode1 temp = head.next ;//因为头节点,不能动,因此我们需要一个辅助变量来遍历
while(true) {
//判断是否到链表最后
if(temp == null) {
break;
}
System.out.println(temp);//输出节点的信息
temp = temp.next;//后移
}
}
添加
思路——首先要找到待添加的位置,然后让temp.next = HeroNode1;
HeroNode1.pre = temp;来完成添加
代码如下、
//添加节点到单向链表;
//思路,当不考虑编号顺序时
//1.找到当前链表的最后节点
//2.将最后这个节点的next指向新的节点
//3。将新的节点的pre指向最后这个几点
public void addNode(HeroNode1 HeroNode1) {
HeroNode1 temp = head;//由于head节点不能动,找个变量辅助查找
while(true) {//遍历链表,找到最后一个节点
if(temp.next == null) {
break;
}
temp = temp.next;//没有找到就将temp后移
}
temp.next = HeroNode1;
HeroNode1.pre = temp;
}
修改
思路——同单向链表一样的方法,就是先找到这个节点,在进行一系列的修改
代码如下
//修改节点的信息,根据no编号来修改,即no编号不能改
public void update(HeroNode1 newHeroNode1) {
//判断是否空
if(head.next == null) {
System.out.println("链表为空~");
return;
}
//找到需要修改的节点,根据no编号
//定义一个辅助变量
HeroNode1 temp = head.next;
boolean flag = false; //表示是否找到该节点
while(true) {
if (temp == null) {
break; //已经遍历完链表
}
if(temp.no == newHeroNode1. no) {
flag = true;
break;
}
temp = temp.next;
}
//根据flag判断是否找到要修改的节点
if(flag) {
temp.name = newHeroNode1.name ;
temp.nickname = newHeroNode1.nickname;
} else { //没有找到
System.out. printf("没有找到编号%d的节点,不能修改\n", newHeroNode1.no);
}
}
删除
思路——这里要好好想想,因为双向链表的特性有一个自我删除,temp.next.pre = temp.pre;temp.pre.next = temp.next;
这里特别要强调一句话,,由于我们不知道这个待删除的节点是不是最后一个节点,因为最后一个节点的next时一个空指针,.next.pre会导致空指针异常,所以我们需要判断一下时候这个节点是否为最后一个节点
操作方法如下:
if(temp.next != null){
temp.next.pre = temp.pre;//如果是最后一个节点的话不执行这句话,否则空指针异常
}
temp.pre.next = temp.next;
代码如下
//删除节点——双向链表
//思路
//1. head 不能动,因此我们需要一个temp辅助节点找到待删除节点
//2. 找到后进行自我删除
public void del(int no) {
HeroNode1 temp = head.next;
boolean flag = false; // 标志是否找到待删除节点的
while(true) {
if(temp == null) { //已经到链表 的最后
System.out.println("链表为空");
break;
}
if(temp.no == no) {
//找到的待删除节点的前一个节点temp
flag = true;
break;
}
temp = temp.next; //temp后移, 遍历
}
//判断flag
if(flag) {
if(temp.next != null){
temp.next.pre = temp.pre;//如果是最后一个节点的话不执行这句话,否则空指针异常
}
temp.pre.next = temp.next;
}else {
System.out.println("这个节点不存在");
}
}
完整代码
package linkedlist;
public class DoubleLinkedList {
public static void main(String[] args) {
//创建节点
HeroNode1 hero1 = new HeroNode1(1, "11","111");
HeroNode1 hero2 = new HeroNode1(2, "22","222");
HeroNode1 hero3 = new HeroNode1(3, "33","333");
HeroNode1 hero4 = new HeroNode1(4, "44","444");
DoubleLinkedListTest singleLinkedListTest = new DoubleLinkedListTest();
singleLinkedListTest.addNode(hero1);
singleLinkedListTest.addNode(hero2);
singleLinkedListTest.addNode(hero3);
singleLinkedListTest.addNode(hero4);
singleLinkedListTest.list();
//创建节点2
// HeroNode11 hero11 = new HeroNode11(1, "11","111");
// HeroNode11 hero21 = new HeroNode11(2, "22","222");
// HeroNode11 hero31 = new HeroNode11(3, "33","333");
// HeroNode11 hero41 = new HeroNode11(4, "44","444");
// DoubleLinkedListTest singleLinkedListTest2 = new DoubleLinkedListTest();
// DoubleLinkedListTest.add(hero21);
// DoubleLinkedListTest.add(hero11);
// DoubleLinkedListTest.add(hero41);
// DoubleLinkedListTest.add(hero31);
// DoubleLinkedListTest.add(hero31);
// DoubleLinkedListTest.list();
//修改节点
HeroNode1 hero311 = new HeroNode1(3, "331","3331");
singleLinkedListTest.update(hero311);
System.out.println("修改后");
singleLinkedListTest.list();
//删除节点
singleLinkedListTest.del(4);
System.out.println("删除后");
singleLinkedListTest.list();
}
}
class DoubleLinkedListTest{
private HeroNode1 head = new HeroNode1(0,"","");//初始化的头节点不妨数据
//显示链表[遍历]
public void list() {
//判断链表是否为空
if(head.next == null) {
System.out.println("链表为空");
return;
}
HeroNode1 temp = head.next ;//因为头节点,不能动,因此我们需要一个辅助变量来遍历
while(true) {
//判断是否到链表最后
if(temp == null) {
break;
}
System.out.println(temp);//输出节点的信息
temp = temp.next;//后移
}
}
//添加节点到单向链表;
//思路,当不考虑编号顺序时
//1.找到当前链表的最后节点
//2.将最后这个节点的next指向新的节点
//3。将新的节点的pre指向最后这个几点
public void addNode(HeroNode1 HeroNode1) {
HeroNode1 temp = head;//由于head节点不能动,找个变量辅助查找
while(true) {//遍历链表,找到最后一个节点
if(temp.next == null) {
break;
}
temp = temp.next;//没有找到就将temp后移
}
temp.next = HeroNode1;
HeroNode1.pre = temp;
}
//修改节点的信息,根据no编号来修改,即no编号不能改
public void update(HeroNode1 newHeroNode1) {
//判断是否空
if(head.next == null) {
System.out.println("链表为空~");
return;
}
//找到需要修改的节点,根据no编号
//定义一个辅助变量
HeroNode1 temp = head.next;
boolean flag = false; //表示是否找到该节点
while(true) {
if (temp == null) {
break; //已经遍历完链表
}
if(temp.no == newHeroNode1. no) {
flag = true;
break;
}
temp = temp.next;
}
//根据flag判断是否找到要修改的节点
if(flag) {
temp.name = newHeroNode1.name ;
temp.nickname = newHeroNode1.nickname;
} else { //没有找到
System.out. printf("没有找到编号%d的节点,不能修改\n", newHeroNode1.no);
}
}
//删除节点——双向链表
//思路
//1. head 不能动,因此我们需要一个temp辅助节点找到待删除节点
//2. 找到后进行自我删除
public void del(int no) {
HeroNode1 temp = head.next;
boolean flag = false; // 标志是否找到待删除节点的
while(true) {
if(temp == null) { //已经到链表 的最后
System.out.println("链表为空");
break;
}
if(temp.no == no) {
//找到的待删除节点的前一个节点temp
flag = true;
break;
}
temp = temp.next; //temp后移, 遍历
}
//判断flag
if(flag) {
if(temp.next != null){
temp.next.pre = temp.pre;//如果是最后一个节点的话不执行这句话,否则空指针异常
}
temp.pre.next = temp.next;
}else {
System.out.println("这个节点不存在");
}
}
}
//定义 HeroNode1节点
class HeroNode1{
public int no;
public String name;
public String nickname;
public HeroNode1 next;//下一个节点
public HeroNode1 pre;//上一个节点
public HeroNode1(int no, String name, String nickname) {
this.no = no;
this.name = name;
this.nickname = nickname;
}
@Override
public String toString() {
return "HeroNode1 [no=" + no + ", name=" + name + ", nickname=" + nickname + "]" ;
}
}