2. 链表(Linked List)之scala

博客围绕链表展开,介绍了链表是有序列表,在内存中不一定连续分布,具有插入、删除快但检索慢的特点,是学习树、森林、图的基础。还给出单链表应用实例,即实现水浒英雄排行榜管理,完成增删改查操作,并提及代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.链表介绍

链表是有序的列表,但是它在内存中是存储如下: 链表在内存中不一定是连续分布. [链表是学习 树,森林,图的基础] // 链表的优点 1. 插入,删除,很快, 缺点是检索速度慢. => 树结构(AVL, 红黑树)

单链表(带头结点)逻辑结构示意图如下:
在这里插入图片描述

2.单链表的应用实例

使用带head头的单向链表实现 –水浒英雄排行榜管理

  1. 完成对英雄人物的增删改查操作, 注: 删除和修改,查找可以考虑学员独立完成
  2. 第一种方法在添加英雄时,直接添加到链表的尾部
  3. 第二种方式在添加英雄时,根据排名将英雄插入到指定位置(如果有这个排名,则添加失败,并给出提示)
  4. 思路分析
    在这里插入图片描述

3.代码实现

  def main(args: Array[String]): Unit = {
    //测试一把链表的创建和遍历
    val singleLinkedList = new SingleLinkedList()
    //创建三个英雄
    val node1 = new HeroNode(1, "宋江", "及时雨")
    val node2 = new HeroNode(2, "卢俊义", "玉麒麟")
    val node3 = new HeroNode(3, "吴用", "智多星")
    val node4 = new HeroNode(4, "张飞", "翼德")

//    singleLinkedList.add(node4)
//    singleLinkedList.add(node1)
//    singleLinkedList.add(node3)
//    singleLinkedList.add(node2)

    singleLinkedList.addByOrder(node4)
    singleLinkedList.addByOrder(node1)
    singleLinkedList.addByOrder(node3)
    singleLinkedList.addByOrder(node2)
    //singleLinkedList.addByOrder(node2)




    println("链表的情况")
    singleLinkedList.list()

    /*
    //测试对结点的修改
    val node5 = new HeroNode(4, "公孙胜", "入云龙")
    singleLinkedList.update(node5)
    printf("链表修改后的情况\n\n")
    singleLinkedList.list()

    //测试一把删除结点
    println()
    println()
    println("删除后的链表情况")
    singleLinkedList.del(3)
    singleLinkedList.del(1)
    singleLinkedList.del(4)
    singleLinkedList.del(12)

    singleLinkedList.list()*/

  }
}

//创建单链表的类
class SingleLinkedList {
  //创建头结点,指向该链表的头部
  val head = new HeroNode(-1, "","")


  //删除一个结点
  def del(no:Int): Unit = {
    //判断是否为空
    if(isEmpty()) {
      println("链表为空")
      return
    }
    //让temp指向head
    var temp = head
    var flag = false
    //遍历,让temp指向,要删除的结点的前一个结点
    breakable {
      while (true) {
        if (temp.next.no == no) {
          //找到
          flag = true
          break()
        }
        //判断temp是否指向链表的倒数第二个结点
        if (temp.next.next == null) {
          break()
        }
        //让temp后移,实现遍历
        temp = temp.next
      }
    }
    //判断flag 的情况
    if(flag) {//找到
      temp.next = temp.next.next
    } else {
      printf("你要删除的结点%d 不存在", no)
    }
  }

  //修改结点信息
  def update(heroNode: HeroNode): Unit = {
    //如果链表为空
    if(isEmpty()) {
      println("链表为空")
      return
    }
    //辅助指针,帮助我们定位到修改的结点
    var temp = head.next
    //需要定义一个变量,标识是否找到该节点
    var flag = false

    breakable {
      while (true) {
        //比较
        if (temp.no == heroNode.no) {
          flag = true
          break()
        }
        //判断temp 是不是到最后
        if (temp.next == null) { //最后
          break()
        }
        //让temp后移,实现遍历
        temp = temp.next
      }
    }
    //判断
    if(flag) { //找到
      temp.nickname = heroNode.nickname
      temp.name = heroNode.name
    } else { // 没有找到
      printf("你要修改的%d英雄不存在.", heroNode.no)
    }
  }

  //添加英雄到单链表
  //默认直接将人加入到链表的最后
  def add(heroNode: HeroNode): Unit = {
    //思路
    //1. 先找到链表的最后结点
    //2. 然后让最后结点.next = 新的结点

    //因为head 不动,因此我们使用一个辅助指针来完成定位
    var temp = head

    breakable {
      while (true) {
        if (temp.next == null) {
          //temp已经到链表的最后
          break()
        }
        temp = temp.next // 让temp后移
      }
    }
    //当退出while时,temp指向最后
    temp.next = heroNode
  }

  //按照no编号的从小到大进行插入
  def addByOrder(heroNode: HeroNode): Unit = {
    //让temp 指向 head
    var temp = head
    var flag = false // 标识是否已经存在这个编号的结点
    breakable {
      //将temp 定位要添加的结点前一个位置,即将新的结点,添加到temp 后面
      while (true) {
        //判断是否是最后一个,如果就是最后一个,也找到位置
        if (temp.next == null) {
          break()
        }

        if (temp.next.no == heroNode.no) { //说明no已经存在
          flag = true
          break()
        } else if (temp.next.no > heroNode.no) { //说明heroNode 就应该加入到temp的后面
          break()
        }

        //将temp 后移,实现遍历
        temp = temp.next

      }
    }
    //当退出while循环后,
    if(flag) { //说明已经有no
      printf("已经存在no=%d 人物", heroNode.no)
    } else {
      heroNode.next = temp.next //
      temp.next = heroNode
    }

  }

  //遍历单向链表
  //思路
  //1. 仍然让temp帮助进行遍历
  //  2.判断链表是否空,空退出, 不为空,就遍历,直到最后结点
  def list(): Unit = {
    if(isEmpty()) {
      println("链表为空,无法遍历")
      return
    }
    //记住,head不能动, 为什么指向 head.next,因为我们有效的数据不包括head
    var temp = head.next
    breakable {
      while (true) {
        //输出当前这个结点的信息
        printf("no=%d name=%s nickname=%s --> ", temp.no, temp.name, temp.nickname)
        //是否是最后结点
        if (temp.next == null) { //是最后结点
          break()
        }
        //如果不是最后的结点,让temp 后移
        temp = temp.next
      }
    }
  }

  def isEmpty(): Boolean = {
    head.next == null
  }
}

class HeroNode(hNo: Int, hName: String, hNickname: String) {
  val no = hNo
  var name = hName
  var nickname = hNickname
  var next: HeroNode = null //默认为null
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值