双向链表 (1)

91 阅读4分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第10天,点击查看活动详情

双向链表

特点:

1>跟单链表相比,多了一个pre,可以指向前一个节点。

2>遍历方法跟单链表一样,但是可以向前查找,也可以向后查找

3>添加,默认是添加到双向链表的最后面

先找到双向链表的最后节点,在将next域更新的同时不要忘记pre域

temp.next=newHeroNode;

newHeroNode.pre=temp;

4>修改节点思路和原来一样

5>删除节点,由于双向链表可以自我删除节点,所以只需要找到待删除节点既可以删除节点

将前一个节点的next指向后一个节点,将后一个节点的pre指向前一个节点

temp.pre.next=temp.next;

这里当是最后一个节点的时候不能执行下面这句话,否则会造成问题,最后一个节点的下一个节点为空,若将空指向了前面,则会出现空指针的使用,所以条语句前面要加一个if语句来判断其是否为空

if(temp.next!=null)

temp.next.pre=temp.pre;

1)由双向链表实现的增删改查

代码实现


//先新建一个头结点,不存放具体的数据

private HeroNode2 head=new HeroNode2(0,"","");

//得到头结点

public HeroNode2 getHead() {

return head;

}

//将及节点添加到后面

public void add(HeroNode2 heroNode) {

//由于head的值不能改变,需要一个变量来辅助进行遍历

HeroNode2 temp=head;

//找到最后一位的链表节点

while(true) {

//只有最后一个节点才会为null,这个时候就可以退出了,这里就是为了找到最后一个节点的位置

if(temp.next==null) {

break;

}

//若没有找到最后一个节点,就将值进行后移,这样程序会不断的前进

temp=temp.next;

}

//此时退出循环后为最后一个节点,然后我们就可以将这个元素添加到最后一个节点的next域,

//并更新节点本身的pre域,从而形成双向链表

temp.next=heroNode;

heroNode.pre=temp;

}

//根据no编号来修改节点的信息,但不能修改no编号

public void updata(HeroNode2 newheroNode) {

//判断是否为空

if(head.next==null) {

System.out.println("链表为空");

return;

}

//找到需要修改的节点,根据no编号,还是要先定义一个辅助变量

HeroNode2 temp=head.next;

//定义是否找到该值

boolean flag=false;

while (true) {

if (temp==null) {

//已经遍历完链表了

break;

}

if(temp.no==newheroNode.no)

{

//已经找到了可以进行

flag=true;

break;

}

temp=temp.next;

}

//先判断flag的值有没有不一样

//根据flag来进行改值

if(flag) {

temp.name=newheroNode.name;

temp.nickname=newheroNode.nickname;

}else {

System.out.printf("没有找到该%d席执行官\n",newheroNode.no);

}

}

//根据no编号来删除节点的信息,由于双向链表可以自我删除节点,所以只需要找到待删除节点既可以删除节点

public void delete(int no) {

//判断是否为空

if(head.next==null) {

System.out.println("链表为空");

return;

}

//找到需要修改的节点,根据no编号,还是要先定义一个辅助变量

HeroNode2 temp=head.next;

//定义是否找到该值

boolean flag=false;

while (true) {

if (temp==null) {

//已经遍历完链表了

break;

}

if(temp.no==no)

{

//已经找到了可以进行

flag=true;

break;

}

temp=temp.next;

}

//根据flag来进行改值

if(flag) {

//将前一个节点的next指向后一个节点,将后一个节点的pre指向前一个节点

temp.pre.next=temp.next;

//这里当是最后一个节点的时候不能执行下面这句话,否则会造成问题,最后一个节点的下一个节点为空,

//若将空指向了前面,则会出现空指针的使用,所以条语句前面要加一个if语句来判断其是否为空

if(temp.next!=null)

{temp.next.pre=temp.pre;}

System.out.printf("第%d席执行官已经删除完毕\n",temp.no+1);

}else {

System.out.printf("没有找到该%d席执行官\n",no);

}

}

//显示所有链表(遍历)

public void list() {

//首先应判断一下链表是否为空

if(head.next==null) {

System.out.println("链表的值为空,不能进行遍历");

return;

}

//跟add()同样的是,由于head的值不能改变,需要一个变量来辅助进行遍历

HeroNode2 temp=head.next;

while(true) {

//首先要有结束语句,否则程序会陷入死循环

//结束条件就是到最后一个节点

if(temp==null) {

break;

}

//若没有跳出程序,就会一直输出显示语句

System.out.println(temp);

//将值进行后移,这样程序会不断的前进

temp=temp.next;

}

}

}

//定义HeroNode,每个HeroNode对象就是一个节点

class HeroNode2{

public int no;

public String name;

public String nickname;

public HeroNode2 pre;  //指向前一个节点,所以要定义一个HeroNode类型的,默认为null

public HeroNode2 next; //指向下一个节点,所以要定义一个HeroNode类型的,默认为null

public HeroNode2(int no, String name, String nickname) {

this.no = no;

this.name = name;

this.nickname = nickname;

}

//为了显示放方便,改写toString

//在改写时不应该放next域,因为next域会一直输出下一个节点,而下个节点也有next域,会将所有节点输出在一行上,所有要将next域去掉

@Override

public String toString() {

return "HeroNode2 [no=" + no + ", name=" + name + ", nickname=" + nickname + "]";

}

 

}