双向链表比单项链表多了一个指向前一个元素的指针,所以双向链表可以倒序遍历。
里一个区别时删除元素时单向链表必须定位到要删除元素的前一个元素处才能删除目标元素,而双向链表可以实现节点的自我删除。
还有一个区别是在有序添加数据时向尾节点添加数据和在链表中间添加数据在单向链表中时相同的操作,在双向链表中必须加以区分。
代码如下:
```java
package linkedlist;
public class DoubleLinkedListDemo {
public static void main(String[] args) {
HeroNode2 hero1 = new HeroNode2(1, "易", "无极剑圣");
HeroNode2 hero2 = new HeroNode2(2, "盖伦", "德玛西亚之力");
HeroNode2 hero3 = new HeroNode2(3, "贾科斯", "武器大师");
HeroNode2 hero4 = new HeroNode2(4, "菲兹", "潮汐海灵");
DoubleLinkedList dl = new DoubleLinkedList();
//向尾部添加数据
// dl.add(hero1);
// dl.add(hero2);
// dl.add(hero3);
// dl.add(hero4);
//有需添加
dl.addByOrder(hero4);
dl.addByOrder(hero2);
dl.addByOrder(hero3);
dl.addByOrder(hero1);
dl.addByOrder(hero4); //插入失败
//输出
dl.showNodes();
//修改
HeroNode2 hero5 = new HeroNode2(1, "拉克丝","光辉女郎");
HeroNode2 hero6 = new HeroNode2(4, "卡特琳娜","不祥之刃");
dl.updateHero(hero6);
dl.updateHero(hero5);
System.out.println("修改后的结果为-----------------------------------------------------------");
dl.showNodes();
//删除
int no = 4;
dl.delNode(no);
// dl.delNode(3);
// dl.delNode(1);
// dl.delNode(2);
System.out.println("删除编号为 " + no + "的英雄后的结果------------------------------------------");
dl.showNodes();
//有序添加
}
}
/**
* 双向链表与单向链表的区别
* 1、单向链表只有指向下一个元素的指针,故只能从头向后遍历。双向链表每一个节点都有前后两个指针,可以双向遍历。
* 2、单向链表删除元素只能先通过临时变量找到要删除元素的前一个元素后在进行删除。双向链表可以实现自我删除
* @author Administrator
*
*/
class DoubleLinkedList{
//声明头节点,头节点一般不做更改,用来指向下一个节点
private HeroNode2 head = new HeroNode2(0, "", "");
public HeroNode2 getHead() {
return head;
}
//向链表尾部追加元素的方法
public void add(HeroNode2 hero) {
//创建临时变量temp
HeroNode2 temp = head;
while(true) {
if(temp.getNext() == null) {
break;
}
temp = temp.getNext();
}
//跳出循环时temp为链表中的最后一个元素
temp.setNext(hero);
hero.setPre(temp);
}
//遍历链表并打印其中的元素
public void showNodes() {
//定义临时变量temp
HeroNode2 temp = head.getNext();
//判断链表是否为空
if(temp == null) {
System.out.println("链表为空!");
return;
}
while(temp != null) {
//输出该节点的信息
System.out.println(temp);
//指针后移
temp = temp.getNext();
}
}
//根据英雄编号修改英雄数据
public void updateHero(HeroNode2 hero) {
//判断链表是否为空
if(head.getNext() == null) {
System.out.println("链表为空!");
return;
}
boolean flag = false;
HeroNode2 temp = head;
while(true) {
//以遍历至链表尾部,未能找到相匹配的数据
if(temp.getNext() == null) {
break;
}
if(temp.getNext().getHeroNo() == hero.getHeroNo()) {
flag = true;
break;
}
//后移指针
temp = temp.getNext();
}
if(flag) {
//如果找到了相应的数据,则修改其中的信息
temp.getNext().setHeroName(hero.getHeroName());
temp.getNext().setHeroNickName(hero.getHeroNickName());
}else {
System.out.println("修改失败,未找到与英雄编号: " + hero.getHeroNo() + "相对应的数据。");
}
}
//按照指定编号删除指定的元素
public void delNode(int no) {
//判断链表是否为空
if(head.getNext() == null) {
System.out.println("链表为空,删除失败!");
return;
}
//设置变量,辅助删除操作
boolean flag = false;
HeroNode2 temp = head.getNext();
while(true) {
//以到链表最后,跳出循环
if(temp == null) {
break;
}
//找到对应的数据,跳出循环,并将flag职位true
if(temp.getHeroNo() == no) {
flag = true;
break;
}
//移动指针
temp = temp.getNext();
}
//根据flag的值判断需要进行的操作
if(flag) {
//节点自我删除
temp.getPre().setNext(temp.getNext());
//这里需要判断当前数据是否为链表中的最后一个数据,若为最后一个数据则没有此步骤!!!!!!!!!!!!!!!!!!!!!!!!!
if(temp.getNext() != null) {
temp.getNext().setPre(temp.getPre());
}
}else {
System.out.println("未找到英雄编号为: " + no + "的数据,删除失败!");
}
}
//按英雄编号顺序向链表中添加数据
public void addByOrder(HeroNode2 hero) {
//设置临时变量用来辅助添加操作 flag 0 表示插入失败,1表示向队尾插入,2表示向队中插入
int flag = 0;
HeroNode2 temp = head;
while(true) {
//已遍历至队尾,向队尾添加数据
if(temp.getNext() == null) {
flag = 1;
break;
}
//如果有编号相同的英雄,则插入失败
if(hero.getHeroNo() == temp.getNext().getHeroNo()) {
break;
//如果当前位置的英雄编号大于要插入数据的英雄编号,则数据插入位置为当前位置之前的位置
}else if(hero.getHeroNo() < temp.getNext().getHeroNo()) {
flag = 2;
break;
}
//移动指针
temp = temp.getNext();
}
switch(flag) {
case 0:
//插入失败
System.out.println("向链表中插入英雄编号为 " + hero.getHeroNo() + "的数据失败,该数据已存在于链表中。");
break;
case 1:
//向尾节点插入数据
temp.setNext(hero);
hero.setPre(temp);
break;
case 2:
//向链表中间插入数据
hero.setNext(temp.getNext());
hero.setPre(temp);
temp.getNext().setPre(hero);
temp.setNext(hero);
break;
}
}
}
/**
* 双向链表的节点类,一个该类的对象表示一个节点,比单向链表的节点对象多了一个pre指针
* @author Administrator
*
*/
class HeroNode2{
private int heroNo; //英雄编号
private String heroName; //英雄名称
private String heroNickName; //英雄昵称
private HeroNode2 next; //节点指针,指向下一个节点
private HeroNode2 pre; //节点指针,指向上一个节点
public HeroNode2(int heroNo , String heroName , String heroNickName) {
this.heroNo = heroNo;
this.heroName = heroName;
this.heroNickName = heroNickName;
}
public HeroNode2 getPre() {
return pre;
}
public void setPre(HeroNode2 pre) {
this.pre = pre;
}
public int getHeroNo() {
return heroNo;
}
public void setHeroNo(int heroNo) {
this.heroNo = heroNo;
}
public String getHeroName() {
return heroName;
}
public void setHeroName(String heroName) {
this.heroName = heroName;
}
public String getHeroNickName() {
return heroNickName;
}
public void setHeroNickName(String heroNickName) {
this.heroNickName = heroNickName;
}
public HeroNode2 getNext() {
return next;
}
public void setNext(HeroNode2 next) {
this.next = next;
}
@Override
public String toString() {
return "HeroNode [heroNo=" + heroNo + ", heroName=" + heroName + ", heroNickName=" + heroNickName + "]";
}
}