双向链表

双向链表

双向链表的增删查改

背景

  • 数据结构——双向链表

  • 博主以b站尚硅谷Java数据结构与算法课进行学习

概念

  • 双向链表遍历方法与单向链表相同,不过双向链表可以向前和向后查找

  • 添加,默认添加到最后

    • 先找到双向链表的最后节点
    • temp.next = newHeroNode
    • newHeroNode.pre = temp
  • 修改,与单链表相同

  • 删除

    • 双向链表可以自我删除
    • 直接找到要删除的节点temp
    • temp.pre.next = temp.next
    • temp.next.pre = temp.pre

问题

  • 使用双向链表实现–水浒传排行榜管理

步骤

  • 与单链表类似

代码实现

  • 修改单链表中HeroNode类

    • 增加pre变量指向链表中上一个节点

    • 代码实现

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      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 + '\'' +
      '}';
      }
      }
  • 遍历

    • 代码实现

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      //遍历双向链表,与单链表一样
      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.next;
      }
      }
  • 添加

    • 代码实现

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      public void add(HeroNode2 heroNode) {
      //当不考虑编号顺序时
      //先找到当前链表的最后节点
      //将最后节点next指向新的节点
      //因为head头节点不能动,所以需要辅助遍历temp
      HeroNode2 temp = head;
      //遍历链表找到最后
      while (true) {
      //代表找到链表的最后
      if (temp.next == null) {
      break;
      }
      //找不到就将temp后移,直至找到退出循环
      temp = temp.next;
      }
      //当退出循环时,temp指向链表的最后
      //形成双向链表
      temp.next = heroNode;
      heroNode.pre = temp;
      }
  • 修改

    • 代码实现

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      //修改双向链表节点
      public void upadate(HeroNode2 newHeroNode) {
      //判断链表是否为空
      if (head.next == null) {
      System.out.println("链表为空");
      }
      //找到需要修改的节点,根据no编号
      //定义一个辅助变量temp
      HeroNode2 temp = head.next;
      boolean flag = false;//表示是否找到该节点
      while (true) {
      if (temp == null) {
      break;//已经遍历完链表了
      }
      if (temp.no == newHeroNode.no) {
      flag = true;//找到
      break;
      }
      temp = temp.next;
      }
      // 根据flag判断是否找到要修改的节点
      if (flag) {
      temp.name = newHeroNode.name;
      temp.nickname = newHeroNode.nickname;
      } else {
      //没有找到
      System.out.println("没有找到");
      }
      }
  • 删除

    • 代码实现

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      //从双向链表删除节点
      //双向链表可以自我删除
      public void del(int no){
      //判断当前链表是否为空
      if(head.next == null){{
      System.out.println("链表为空,不能删除");
      }
      HeroNode2 temp = head.next;//辅助变量直接指向要删除的节点
      boolean flag = false;//判断是否找到要删除节点的标志
      while(true){
      if(temp == null){
      break;//到了链表最后
      }
      if(temp.no == no){//找到要删除的节点
      flag = true;
      break;
      }
      temp = temp.next;//后移
      }if(flag){//找到执行
      temp.pre.next = temp.next;
      if (temp.next != null) {
      temp.next.pre = temp.pre;//存在风险,如果是最后一个节点,不需要执行这段代码,否则会出现空指针异常
      }
      }
      }else{//没有找到执行
      System.out.printf("要删除的节点%d不存在\n",no);
      }

      }