使用带head头的双向链表实现-水浒传英雄排行榜管理单向链表的缺点分析
分析双向链表的遍历,添加,修改,删除的操作思路—代码实现
双向链表增删改查代码实现
增加
//添加一个节点到双向链表的最后
public void add(HeroNode2 heroNode2){
//因为head节点不能动,因此我们需要一个辅助遍历temp
HeroNode2 temp =head;
//遍历链表,找到最后
while (true){
//找到链表的最后
if (temp.next==null){
break;
}
//如果没有找到最后的,将temp后移
temp=temp.next;
}
//但退出while循环时,temp就指向链表的最后
//形成一个双向链表
temp.next=heroNode2;
temp.pre=temp;
}
删除
//从双向链表中删除一个节点
//说明 1.对于双向链表,我们可以直接找到要删除的这个节点
//2.找到后,自我删除即可
public void del(int no){
//判断当前链表是否为空
if (head.next==null){
System.out.println("链表为空不能删除");
}
HeroNode2 temp=head.next;//辅助节点
boolean flag=false;//标志是否找到待删除节点的
while (true){
if (temp==null){//已经到链表的最后节点的next
break;
}
if (temp.no==no){
//找到待删除节点的前一个节点temp
flag=true;
break;
}
temp=temp.next;//temp后移,遍历
}
//判断flag
if (flag){//找到
//可以删除
// temp.next=temp.next.next;//单向链表的删除方式
temp.pre.next=temp.next;
//这里代码有问题,如果是最后一个节点,就不需要执行下面这句话,否则出现空指针
if (temp.next != null){
temp.next.pre=temp.pre;
}
}else {
System.out.printf("要删除的%d 节点不存在\n",no);
}
}
修改
//修改一个节点的内容,可以看到双向链表的节点内容修改和单向链表一样
//只是节点类型改成HeroNode2
public void update(HeroNode2 heroNode2){
//判断是否为空
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==heroNode2.no){
//找到
flag=true;
break;
}
temp=temp.next;
}
//根据flag判断sf找到要修改的节点
if (flag){
temp.name=heroNode2.name;
temp.nickname=heroNode2.nickname;
}else {//没有找到
System.out.printf("没有找到编号%d的节点,不能修改\n",heroNode2.no);
}
}
**查看**
//显示链表(通过遍历)
public void list(){
//判断链表的是否为空
if(head.next==null){
System.out.println("链表为空");
return;
}
//因为头节点不能动,因此我们需要一个辅助变量来遍历
HeroNode2 temp=head.next;
while (true) {
//判断是否到链表最后
if (temp == null) {
break;
}
//输出节点信息
System.out.println(temp);
//将temp后移,一定要小心,不然就是个死循环
temp = temp.next;
}
}
测试
/
/测试
System.out.println("双向链表的测试");
//先创建节点
HeroNode2 hero1 = new HeroNode2(1, "松江", "及时雨");
HeroNode2 hero2 = new HeroNode2(3, "吴用", "智多星");
HeroNode2 hero3 = new HeroNode2(2, "卢俊义", "玉麒麟");
HeroNode2 hero4 = new HeroNode2(4, "林冲", "豹子头");
//创建一个双向链表对象
DoubleLinkedList doubleLinkedList = new DoubleLinkedList();
doubleLinkedList.add(hero1);
doubleLinkedList.add(hero2);
doubleLinkedList.add(hero3);
doubleLinkedList.add(hero4);
doubleLinkedList.list();
//修改
HeroNode2 newHerNode=new HeroNode2(3,"唐三","蓝银草");
doubleLinkedList.update(newHerNode);
System.out.println("修改后的链表情况");
doubleLinkedList.list();
//删除
doubleLinkedList.del(4);
System.out.println("删除后的链表情况");
doubleLinkedList.list();
实现
完整代码
package com.linkedlist;
public class DoubleLinkedListDemo {
public static void main(String[] args){
//测试
System.out.println("双向链表的测试");
//先创建节点
HeroNode2 hero1 = new HeroNode2(1, "松江", "及时雨");
HeroNode2 hero2 = new HeroNode2(3, "吴用", "智多星");
HeroNode2 hero3 = new HeroNode2(2, "卢俊义", "玉麒麟");
HeroNode2 hero4 = new HeroNode2(4, "林冲", "豹子头");
//创建一个双向链表对象
DoubleLinkedList doubleLinkedList = new DoubleLinkedList();
doubleLinkedList.add(hero1);
doubleLinkedList.add(hero2);
doubleLinkedList.add(hero3);
doubleLinkedList.add(hero4);
doubleLinkedList.list();
//修改
HeroNode2 newHerNode=new HeroNode2(3,"唐三","蓝银草");
doubleLinkedList.update(newHerNode);
System.out.println("修改后的链表情况");
doubleLinkedList.list();
//删除
doubleLinkedList.del(2);
System.out.println("删除后的链表情况");
doubleLinkedList.list();
}
}
//创建一个双向链表的类
class DoubleLinkedList{
//先初始化以一个头节点,头节点不要动,不放具体数据
private HeroNode2 head =new HeroNode2(0,"","");
//返回头节点
public HeroNode2 getHead(){
return head;
}
//显示链表(通过遍历)
public void list(){
//判断链表的是否为空
if(head.next==null){
System.out.println("链表为空");
return;
}
//因为头节点不能动,因此我们需要一个辅助变量来遍历
HeroNode2 temp=head.next;
while (true) {
//判断是否到链表最后
if (temp == null) {
break;
}
//输出节点信息
System.out.println(temp);
//将temp后移,一定要小心,不然就是个死循环
temp = temp.next;
}
}
//添加一个节点到双向链表的最后
public void add(HeroNode2 heroNode2){
//因为head节点不能动,因此我们需要一个辅助遍历temp
HeroNode2 temp =head;
//遍历链表,找到最后
while (true){
//找到链表的最后
if (temp.next==null){
break;
}
//如果没有找到最后的,将temp后移
temp=temp.next;
}
//但退出while循环时,temp就指向链表的最后
//形成一个双向链表
temp.next=heroNode2;
temp.pre=temp;
}
//修改一个节点的内容,可以看到双向链表的节点内容修改和单向链表一样
//只是节点类型改成HeroNode2
public void update(HeroNode2 heroNode2){
//判断是否为空
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==heroNode2.no){
//找到
flag=true;
break;
}
temp=temp.next;
}
//根据flag判断sf找到要修改的节点
if (flag){
temp.name=heroNode2.name;
temp.nickname=heroNode2.nickname;
}else {//没有找到
System.out.printf("没有找到编号%d的节点,不能修改\n",heroNode2.no);
}
}
//从双向链表中删除一个节点
//说明 1.对于双向链表,我们可以直接找到要删除的这个节点
//2.找到后,自我删除即可
public void del(int no){
//判断当前链表是否为空
if (head.next==null){
System.out.println("链表为空不能删除");
}
HeroNode2 temp=head.next;//辅助节点
boolean flag=false;//标志是否找到待删除节点的
while (true){
if (temp==null){//已经到链表的最后节点的next
break;
}
if (temp.no==no){
//找到待删除节点的前一个节点temp
flag=true;
break;
}
temp=temp.next;//temp后移,遍历
}
//判断flag
if (flag){//找到
//可以删除
// temp.next=temp.next.next;//单向链表的删除方式
temp.pre.next=temp.next;
//这里代码有问题,如果是最后一个节点,就不需要执行下面这句话,否则出现空指针
if (temp.next != null){
temp.next.pre=temp.pre;
}
}else {
System.out.printf("要删除的%d 节点不存在\n",no);
}
}
}
//定义一个HeroNode,每个HeroNode对象就是一个节点
class HeroNode2{
public int no;
public String name;
public String nickname;
public HeroNode2 next;//指向下一个节点,默认为null
public HeroNode2 pre;//指向前一个节点,默认为null
//构造器
public HeroNode2(int no,String name, String nickname){
this.no=no;
this.name=name;
this.nickname=nickname;
}
//为了显示方便 重新写下toString
@Override
public String toString(){
return "HeroNode[no"+no+",name="+name+",nickname="+nickname+"]";
}
}