Java数据结构之单链表——day03

1. 目的:使用Java实现一个简单的链表

  1. 链表的存储对象为自定义Hero类的实例化;

  2. 定义链表的节点类HeroNode;

  3. 定义链表类SingleLinkedList;

  4. 链表类SingleLinkedList应具有如下几个方法: 

  1. addHero( )方法:用来向链表中添加英雄;
  2. addHeroByIdASC( ):以ID作为标准升序添加英雄;
  3. dropHeroByID( )方法:通过ID删除英雄;
  4. updateHeroNameByID( ):通过ID修改英雄的名字;
  5. updateHeroNicknameByID( ):通过ID修改英雄昵称;
  6. updateHeroByID( ):通过ID修改英雄的名字与昵称;
  7. listAll( ):显示链表所有数据。

2.Hero类的实现

package 单链表;

/**
 * @Classname Hero
 * @Description TODO
 * @Date 2022/4/10 13:02
 * @Created by jiawen
 */
public class Hero {
    String name;
    String nikeName;
    int id;

    public Hero(String name, String nikeName, int id) {
        this.name = name;
        this.nikeName = nikeName;
        this.id = id;
    }

    @Override
    public String toString() {
        return "Hero{" +
                "name='" + name + '\'' +
                ", nikeName='" + nikeName + '\'' +
                ", id=" + id +
                '}';
    }
}

3.节点类HeroNode的实现

        节点类包含两个基本属性:(1) hero属性,表示该节点的Hero数据;(2)HeroNode类型的nextHeroNode 属性,表示该链表节点的下一个数据。

        这里修改了toString方法,增加了一个判断语句,这样可以解决在后面遍历链表时最后一个数据不会被显示的问题。

package 单链表;

/**
 * @Classname HeroNode
 * @Description TODO
 * @Date 2022/4/10 13:03
 * @Created by jiawen
 */
public class HeroNode {
    Hero hero;
    HeroNode nextHeroNode;

    @Override
    public String toString() {
        if(this.nextHeroNode==null){
            return "HeroNode{" +
                    "hero=" + hero +
                    ", nextHeroNodeName=null"+
                    '}';
        }
        return "HeroNode{" +
                "hero=" + hero +
                ", nextHeroNodeName=" + nextHeroNode.hero.name +
                '}';
    }

    public HeroNode(Hero hero) {
        this.hero = hero;

    }
}

4.链表类的实现

        链表默认有一个表头,所以需首先初始化一个头节点

package 单链表;

/**
 * @Classname SingleLinkedList
 * @Description TODO
 * @Date 2022/4/10 13:08
 * @Created by jiawen
 */
public class SingleLinkedList {
    HeroNode headHeroNode = new HeroNode(new Hero("HEAD", "HEAD", -1));//头节点的初始化,参数可以随便填
    /*
            1:新节点的插入一定在表末尾,需要先找到末尾;
            2:当指针所在节点上的下个节点属性为null,证明到了链表尾部,新节点的插入应该在指针后面;
            3:找到则跳出while循环,否则指针后移;
            4:一旦跳出了while循环,意味着指针在最后一个节点上,将这个节点的nextHeroNode属性赋值为新节点即可。
            */
    public void addHero(HeroNode heroNode) {

        HeroNode temp = headHeroNode;//定义一个指针temp,一开始指向头节点
        while (true) {

            if (temp.nextHeroNode == null) {
                break;
            }
            temp = temp.nextHeroNode;
        }
        temp.nextHeroNode = heroNode;

    }
    /*依旧通过指针temp来遍历*/
    public void listAll() {


        if (headHeroNode.nextHeroNode == null) {
            System.out.println("This list is is empty!");
            return;
        }
        HeroNode temp = headHeroNode.nextHeroNode;
        while (true) {

            if (temp == null) {
                break;
            }else{
                System.out.println(temp);
                temp = temp.nextHeroNode;
            }
        }


    }

    public void addByIdASC(HeroNode heroNode) {
        HeroNode temp = headHeroNode;
        boolean flag = true;//这个flag很重要,它在添加节点ID与已有的节点ID重复时被取反
        while (true) {
            if (temp.nextHeroNode == null) {//这个判断必须要有,否则下面的if在ID重复时将会一直在while循环无法跳出
                break;
            }
            if (temp.nextHeroNode.hero.id > heroNode.hero.id) {//如果指针的下一个id比待插入的要大,证明这个待插入的数据在指针后
                break;
            } else if (temp.nextHeroNode.hero.id == heroNode.hero.id) {//证明待插入数据的ID与已有的冲突,不允许插入,并将flag取反
                flag = !flag;
                break;
            } else {//证明指针的下一个数据ID比待插入的要小,所以指针仍然需要后移
                temp = temp.nextHeroNode;

            }
        }
        /*
            flag如果取反了,证明想要插入的数据已经存在,否则将数据插入,
            注意更改顺序,应该先更改待插入数据的nextHeroNode,再更改待插入数据前面那个数据的nextHeroNode*/
        if (!flag) {
            System.out.println("The data ID which you are going to insert already exists");
        } else {
            heroNode.nextHeroNode = temp.nextHeroNode;
            temp.nextHeroNode = heroNode;
        }
    }
    //后面四个方法实现方式大同小异,重点是对temp指针的理解
    public void updateHeroNameByID(int id, String udateName) {
        if (headHeroNode.nextHeroNode == null) {
            System.out.println("This list is empty!");
            return;
        }
        HeroNode temp = headHeroNode.nextHeroNode;
        boolean flag = false;
        while (true) {
            if (temp.nextHeroNode == null) {//这个判断条件大量出现,作用是防止当下面的if语句没有满足条件时,指针temp会不断向后,出现NullPointException
                break;                      //这个if的作用就是确保在没有找到时程序可以正常跳出while循环
            }
            if (temp.hero.id == id) {
                flag = !flag;
                break;
            } else {
                temp = temp.nextHeroNode;
            }

        }
        if (!flag) {
            System.out.println("No hero found for ID = " + id);
        } else {
            temp.hero.name = udateName;
        }

    }

    public void updateHeroNicknameByID(int id, String udateNickname) {
        if (headHeroNode.nextHeroNode == null) {
            System.out.println("This list is empty!");
            return;
        }
        HeroNode temp = headHeroNode.nextHeroNode;
        boolean flag = false;
        while (true) {
            if (temp.nextHeroNode == null) {//这个判断条件大量出现,作用是防止当下面的if语句没有满足条件时,指针temp会不断向后,出现NullPointException
                break;                      //这个if的作用就是确保在没有找到时程序可以正常跳出while循环
            }
            if (temp.hero.id == id) {
                flag = !flag;
                break;
            } else {
                temp = temp.nextHeroNode;
            }

        }
        if (!flag) {
            System.out.println("No hero found for ID = " + id);
        } else {
            temp.hero.nikeName = udateNickname;
        }

    }

    public void updateHeroByID(int id, String updateName, String udateNickname) {
        if (headHeroNode.nextHeroNode == null) {
            System.out.println("This list is empty!");
            return;
        }
        HeroNode temp = headHeroNode.nextHeroNode;
        boolean flag = false;
        while (true) {
            if (temp.nextHeroNode == null) {//这个判断条件大量出现,作用是防止当下面的if语句没有满足条件时,指针temp会不断向后,出现NullPointException
                break;                      //这个if的作用就是确保在没有找到时程序可以正常跳出while循环
            }
            if (temp.hero.id == id) {
                flag = !flag;
                break;
            } else {
                temp = temp.nextHeroNode;
            }

        }
        if (!flag) {
            System.out.println("No hero found for ID = " + id);
        } else {
            temp.hero.name = updateName;
            temp.hero.nikeName = udateNickname;
        }

    }

    public void dropHeroByID(int id) {
        if (headHeroNode.nextHeroNode == null) {
            System.out.println("This list is empty!");
            return;
        }
        HeroNode temp = headHeroNode;
        boolean flag = false;
        while (true) {

            if (temp.nextHeroNode == null) {
                break;
            }
            if (temp.nextHeroNode.hero.id == id) {
                flag = !flag;
                break;
            } else {
                temp = temp.nextHeroNode;
            }
        }
        if (!flag) {
            System.out.println("No hero found for ID = " + id);
        } else {
            temp.nextHeroNode = temp.nextHeroNode.nextHeroNode;

        }
    }


}

5.编写测试Demo测试代码 

package 单链表;

/**
 * @Classname Demo
 * @Description TODO
 * @Date 2022/4/10 13:42
 * @Created by jiawe
 */
public class Demo {
    public static void main(String[] args) {

        HeroNode heroNode1 = new HeroNode(new Hero("关羽", "云长",1));
        HeroNode heroNode2 = new HeroNode(new Hero("张飞", "翼德",2));
        HeroNode heroNode3 = new HeroNode(new Hero("赵云", "子龙",3));
        HeroNode heroNode4 = new HeroNode(new Hero("马超", "孟起",4));
        HeroNode heroNode5 = new HeroNode(new Hero("黄忠", "汉升",5));
        SingleLinkedList singleLinkedList = new SingleLinkedList();

        singleLinkedList.addByIdASC(heroNode1);
        singleLinkedList.addByIdASC(heroNode5);
        singleLinkedList.addByIdASC(heroNode2);
        singleLinkedList.addByIdASC(heroNode4);
        singleLinkedList.addByIdASC(heroNode3);

        //singleLinkedList.dropHeroByID(8);
        //singleLinkedList.listAll();
        //几种方法分别测试即可...
    }
}

难点:对temp指针的理解

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值