单链表和双链表、循环链表

1、链表(Linked List)介绍

1.1、内存结构

  • 内存上来看:链表存储空间不连续(不像数组)
  • 假设有一个线性表为(a1,a2,a3,a4,a5,a6),则其对应的带有头结点的链表表示及存储结构如图所示,其中head指针的值为2020H。
    在这里插入图片描述

1.2 、逻辑结构

  • 逻辑上来看:链表属于线性结构
  • 含有n个元素的线性表通过每个结点的指针域链接成一个链表。又由于此链表的每个结点中只有一个指向后继的指针,所以称其为单链表或线性链表。下图的单链表是带有头结点的单链表,头结点的作用是方便单链表的特殊操作,简化代码。其中,头指针head指向链表的头结点,各元素结点的指针指向下一个结点,而最后一个结点的指针为“空”(NULL)。从头指针开始便可沿着链找到链表各个元素,因此可用头指针来表示一个单链表。

在这里插入图片描述

2、单链表的实现

2.1、水浒英雄榜

  • 单链表的应用实例
  • 使用带head头的单向链表实现 –水浒英雄排行榜管理
  • 完成对英雄人物的增删改查操作, 注: 删除和修改,查找可以考虑学员独立完成,也可带学员完成
  • 第一种方法在添加英雄时,直接添加到链表的尾部
  • 第二种方式在添加英雄时,根据排名将英雄插入到指定位置(如果有这个排名,则添加失败,并给出提示)
    在这里插入图片描述

2.2、链表节点定义

  • no :英雄编号
  • name :英雄名字
  • nickName :英雄昵称
  • next :指向下一个 HeroNode 节点
//定义HeroNode,每个HeroNode对象就是一个节点
class HeroNode{
   
    public int no;                          //英雄的编号
    public String name;                     //英雄的名字
    public String nickname;                //英雄的称号
    public HeroNode next;                  //指向下一节点

    //构造器
    public HeroNode(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 + '\'' +
                '}';
    }
}

2.3、链表定义

  • Head :头结点不存放数据,仅仅作为当前链表的入口
  • head 字段的值不能改变,一旦改变,就丢失了整个链表的入口,我们也就无法通过 head 找到链表了
/定义SingleLikedList管理英雄
class SingleLikedList{
   
    //先初始化头结点,固定不要动,不存放数据
    private HeroNode head = new HeroNode(0,"","");

2.4、遍历链表

  • 定义辅助变量 temp ,相当于一个指针,指向当前节点
  • 何时遍历完成?temp == null 表明当前节点为 null ,即表示已到链表末尾
  • 如何遍历?temp = temp.next ,每次输出当前节点信息之后,temp 指针后移
//显示链表【遍历】
    public void list(){
   
        //链表先判空
        if (head.next == null){
   
            System.out.println("链表为空");
            return;
        }
        //添加一个辅助的节点temp,因为head节点不能动
        HeroNode temp = head.next;
        while (true){
   
            if (temp == null)break;         //已经遍历完退出循环
            System.out.println(temp);             //输出链表信息
            temp = temp.next;                     //继续遍历,temp后移一个节点
        }
    }

2.5、添加节点

  • 代码思路

在这里插入图片描述

  • 定义辅助变量 temp ,相当于一个指针,指向当前节点
  • 如何在链表末尾插入节点?
  • 首先需要遍历链表,找到链表最后一个节点,当 temp.next == null时,temp 节点指向链表最后一个节点
  • 然后在 temp 节点之后插入节点即可:temp.next = heroNode
    在这里插入图片描述
//添加节点到单向链表,第二种方式有顺序,根据排名添加
    public void addByOrder(HeroNode heroNode){
   
        //添加一个辅助的节点temp,因为head节点不能动
        //找到temp是位于添加位置的前一个节点,否则添加不了
        HeroNode temp = head;
        boolean flag = false;                     //flag代表需要添加的节点是否存在,默认false
        while (true){
   
            if (temp.next == null)break;         //已经遍历完退出循环
            if (temp.next.no > heroNode.no){
        //位置找到,就在temp后面插入,temp的下一个节点和要添加的节点比较。
                break;
            }else if (temp.next.no == heroNode.no){
   
                flag = true;                      //代表需要添加的heroNode节点存在
                break;
            }
            temp = temp.next;                     //继续遍历,temp后移一个节点
        }
        //遍历完链表后判断flag的值
        if (flag){
                                   //不能添加,节点已经存在
            System.out.printf("准备插入的英雄编号%d已经存在,不能加入\n",heroNode
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值