一、单向链表缺点
1、单向链表,查找的方向只能是一个方向,而双向链表可以向前和向后查找
2、单向链表不能自我删除,需要依靠辅助节点,而双向链表可以自我删除
二、基本功能实现
(一)生成节点【双向链表节点类(DHeroNode类)】
class DHeroNode{
public int no;//编号
public String name;//人物名字
public String nickname;//人物外号
public DHeroNode next;//指向下一个节点
public DHeroNode pre;//指向前一个节点
public DHeroNode(int hno,String hname,String hnickname){
this.no=hno;
this.name=hname;
this.nickname=hnickname;
}
@Override
public String toString() {
return "HeroNode [no="+no+",name="+name+",nickname="+nickname+"]";
}
}
创建构造器,比起单链表多了变量pre,重写ToString()方法
(二)创建双向链表,并创建头节点、写入功能方法
class DoubleLinkedList{
//初始化头节点
private DHeroNode head=new DHeroNode(0,"","");
public DHeroNode getHead() {
return head;
}
}
1、显示遍历:
和单链表一样,只是还可以向前查找
//显示链表,遍历
public void list(){
if(head.next==null){
//头指针next为空
System.out.println("链表为空!");
return;
}
DHeroNode temp=head.next;
while (true){
if(temp==null){
break;
}
System.out.println(temp);//已经重写了toString方法
temp=temp.next;
}
}
2、添加:
1)找到双向链表最后这个节点
2)temp.next=newHeroNode
3)newHeroNode.pre=temp
//添加节点
public void add(DHeroNode heroNode){
//辅助节点
DHeroNode temp=head;
//遍历链表
while (true){
if(temp.next==null){
break;
}
//若没找到最后,temp后移
temp=temp.next;
}
//退出循环时,temp指向链表最后
temp.next=heroNode;
heroNode.pre=temp;
}
3、修改:
和单链表原理一样
public void update(DHeroNode heroNode){
if(head.next==null){
System.out.println("链表为空!");
}
DHeroNode temp=head.next;
boolean flag=false;
while (true){
if(temp==null){
break;//指的是已经遍历完链表
}
if(temp.no==heroNode.no){
flag=true;//找到同样编号的英雄
break;
}
temp=temp.next;
}
if(flag==true){
temp.name= heroNode.name;
temp.nickname= heroNode.nickname;
}else {
System.out.println("没有找到该节点!");
}
}
4、删除:
1)双向链表可以实现自我删除,直接找到要删除的节点
2)temp.pre.next=temp.next
3)temp.next.pre=temp.pre
public void delete(int no){
if(head.next==null){
System.out.println("链表为空");
return;
}
DHeroNode temp=head.next;
boolean flag=false;//是否找到待删除节点
while (true){
if(temp==null){
break;
}
if(temp.no==no){
flag=true;
break;
}
temp=temp.next;
}
if(flag){
temp.pre.next=temp.next;
if(temp.next!=null){
temp.next.pre=temp.pre;//如果是最后一个节点,此语句不需要执行
}
}else {
System.out.println("待删除节点不存在!");
}
}
5、根据编号指定位置添加节点
public void insertadd(DHeroNode heroNode){
DHeroNode temp=head;
boolean flag=false;//添加编号是否存在,默认false
while (true){
//temp已经在链表最后
if(temp.next==null){
break;
}
//当temp的下一个节点序号大于新节点序号时,位置找到
if(temp.next.no>heroNode.no){
break;
}else if(temp.next.no== heroNode.no){
//说明heroNode已经存在
flag=true;
break;
}
temp=temp.next;
}
if(flag){
System.out.println("该英雄已经存在!");
}else {
//新英雄还不在链表中
heroNode.next=temp.next;
temp.next=heroNode;
heroNode.pre=temp.next.pre;//若temp.next=null,此语句不执行
if(temp.next!=null){
temp.next.pre=heroNode;
}
}
}
三、测试代码
public class DoubleLinkedListDemo {
public static void main(String[] args) {
//创建初始节点
DHeroNode heroNode1=new DHeroNode(1,"亚索","新手村领路人");
DHeroNode heroNode2=new DHeroNode(2,"孙悟空","齐天大圣");
DHeroNode heroNode3=new DHeroNode(3,"小乔","美人");
DHeroNode heroNode4=new DHeroNode(4,"武则天","女帝");
System.out.println("________________添加英雄________________________");
//创建双向链表,添加节点
DoubleLinkedList doubleLinkedList=new DoubleLinkedList();
doubleLinkedList.add(heroNode1);
doubleLinkedList.add(heroNode2);
doubleLinkedList.add(heroNode3);
doubleLinkedList.add(heroNode4);
System.out.println("________________显示英雄排行榜________________________");
//显示链表
doubleLinkedList.list();
System.out.println("________________修改3号英雄________________________");
//修改节点信息
DHeroNode newDHeroNode=new DHeroNode(3,"李白","诗仙");
doubleLinkedList.update(newDHeroNode);
doubleLinkedList.list();
System.out.println("________________删除2、4号英雄后________________________");
//删除节点
doubleLinkedList.delete(2);
doubleLinkedList.delete(4);
doubleLinkedList.list();
System.out.println("________________插入2、4号英雄后________________________");
//根据编号指定位置插入节点
doubleLinkedList.insertadd(heroNode2);
doubleLinkedList.insertadd(heroNode4);
doubleLinkedList.list();
}
}