java之双向链表
双向链表就是每一个节点不仅有一个next属性指向下一个节点,还有一个 pre属性指向前一个节点。这样的话,在修改代码的时候, 仅需在节点类中添加一个pre的属性,在链表类的方法中,如果要对节点作 增删改,使得节点的pre属性指向前一个节点的位置即可。
区别于单链表,双向链表在作对节点的删除的时候,可以不使用tmp指向待删除节点的前一个位置,直接使用tmp指向待删除节点。
总体代码如下
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 test = new DoubleLinkedList();
// test.addNode(hero1);
// test.addNode(hero2);
// test.addNode(hero4);
// test.addNode(hero3);
test.addNodeByOrder(hero3);
test.addNodeByOrder(hero2);
test.addNodeByOrder(hero1);
test.addNodeByOrder(hero4);
HeroNode2 newHero = new HeroNode2(2,"小卢","小玉");
test.modifyNode(newHero);
test.showList();
test.delNode(2);
test.showList();
test.delNode(4);
test.showList();
}
}
class HeroNode2{
int no ;
String name;
String nickname;
HeroNode2 next;
HeroNode2 pre;
public HeroNode2(int no,String name,String nickname){
this.no = no;
this.name = name;
this.nickname = nickname;
}
@Override
public String toString() {
return "HeroNode [no=" + no + ", name=" + name + ", nickname=" + nickname + "]";
}
}
class DoubleLinkedList{
HeroNode2 head = new HeroNode2(0,"","");
public void addNode(HeroNode2 node){
HeroNode2 tmp = head;
while(true){
if(tmp.next == null)
{
tmp.next = node;
node.pre = tmp;
break;
}
tmp = tmp.next;
}
}
public void addNodeByOrder(HeroNode2 node){
HeroNode2 tmp = head;
boolean flag = false;
while(true){
if(tmp.next == null){
break;
}else if(tmp.next.no > node.no){
break;
}else if(tmp.next.no == node.no )
{
flag = true;
break;
}
tmp = tmp.next;
}
if(flag == true)
{
System.out.printf("输入的编号%d已存在",node.no);
System.out.println();
}
else{
node.next = tmp.next; //是tmp.next给node.next,不要记成了tmp.next.next,单链表的中delNode才这么用,别记混了。null是没有.next 属性的
tmp.next = node;
node.pre = tmp;
if(tmp.next.next != null)
tmp.next.next.pre = node;
}
}
//tmp按顺序添加的时候,tmp还是只能执行要插入元素的前一个值,不能为要插入元素的后一个值,因为如果tmp为null,就无法定位tmp前一个元素了
// public void addNodeByOrder(HeroNode2 node){
// HeroNode2 tmp = head.next;
// boolean flag = false;
// while(true){
// if(tmp == null)
// break;
// if(tmp.no == node.no){
// flag = true;
// break;
// }
// if(tmp.no > node.no){
// break;
// }
// tmp = tmp.next;
// }
// if(flag){
// System.out.println("节点已存在,不可重复添加");
//
// }
// else{
// if (tmp != null) {
// tmp = node.next;
// tmp.pre.next = node;
// }
// else{
// tmp = node; //如果tmp为null,则无法定位到tmp前面的对象,故此方法不行
// }
// }
// }
public void modifyNode(HeroNode2 node){
HeroNode2 tmp = head;
if(tmp.next == null)
{
System.out.println("列表为空");
return;
}
while(true){
if(tmp.next == null){
System.out.println("没有找到要修改的节点");
break;
}
if(tmp.next.no == node.no){
tmp.next.name = node.name;
tmp.next.nickname = node.nickname;
System.out.println("已找到要修改的节点,修改节点成功");
break;
}
tmp = tmp.next;
}
}
//删除节点的时候,也可以使用tmp指向待删除节点前一个位置的方法
// public void delNode(int no){
// HeroNode2 tmp = head;
// if(tmp.next == null)
// {
// System.out.println("链表为空");
// return;
// }
// while(true){
// if(tmp.next == null){
// System.out.println("没有找到要删除的节点");
// break;
// }
// if(tmp.next.no == no){
// tmp.next = tmp.next.next;
System.out.println(tmp.next.next);
// if(tmp.next != null) //这儿千万不能写成tmp.next.next,因为上一条语句的关系,否则null.pre或者null.next会有空指针的异常。
// {
// tmp.next.pre = tmp;
// }
// System.out.println("删除节点成功");
// break;
// }
// tmp = tmp.next;
// }
// }
//使用双向链表作删除节点的时候,可以不用向单向链表那样把tmp定位到目标节点的前一个位置,直接把tmp定位到目标节点即可。
public void delNode(int n){
HeroNode2 tmp = head.next;
if(tmp == null){
System.out.println("链表为空");
}
while(true)
{
if(tmp == null){
System.out.println("没有找到要删除的元素");
break;
}
if(tmp.no == n){
tmp.pre.next = tmp.next;
if(tmp.next != null)
tmp.next.pre = tmp.pre;
System.out.println("删除节点成功");
break;
}
tmp = tmp.next;
}
}
public void showList(){
HeroNode2 tmp;
if(head.next == null)
{
System.out.println("列表是空的");
return;
}
tmp = head;
tmp = tmp.next;
while(true){
if(tmp.next == null)
{
System.out.println(tmp);
break;
}
System.out.println(tmp);
tmp = tmp.next;
}
}
}
运行结果
已找到要修改的节点,修改节点成功
HeroNode [no=1, name=宋江, nickname=及时雨]
HeroNode [no=2, name=小卢, nickname=小玉]
HeroNode [no=3, name=吴用, nickname=智多星]
HeroNode [no=4, name=林冲, nickname=豹子头]
删除节点成功
HeroNode [no=1, name=宋江, nickname=及时雨]
HeroNode [no=3, name=吴用, nickname=智多星]
HeroNode [no=4, name=林冲, nickname=豹子头]
删除节点成功
HeroNode [no=1, name=宋江, nickname=及时雨]
HeroNode [no=3, name=吴用, nickname=智多星]