4、链表

 基本介绍

概念

链表是一种物理存储单元上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。

特点

  1. 链表是以节点的方式来存储,是链式存储。

  2. 每个节点包含 data 域, next 域:指向下一个节点。

  3. 如图:发现链表的各个节点不一定是连续存储。

  4. 链表分带头节点的链表和没有头节点的链表,根据实际的需求来确定。

 

 单链表

单链表创建和遍历的分析实现

添加(创建):

  1. 先创建一个head头节点,作用就是表示单链表的头。
  2. 之后每添加一个结点,就直接加入到链表的最后 。 no :编号 name: 名字 昵称:nickName 

 

//java版最新代码:

package com.atguigu;

public class SingleLinkedListDemo {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        // 测试单向链表的添加和遍历
        HeroNode hero1 = new HeroNode(1, "宋江", "及时雨");
        HeroNode hero2 = new HeroNode(3, "宋江3", "及时雨3");
        HeroNode hero3 = new HeroNode(4, "宋江4", "及时雨4");
        HeroNode hero4 = new HeroNode(2, "宋江2", "及时雨2");
        // 创建一个单向链表
        SingleLinkedList singleLinkedList = new SingleLinkedList();
        // singleLinkedList.add(hero1);
        // singleLinkedList.add(hero2);
        // singleLinkedList.add(hero3);
        // singleLinkedList.add(hero4);

        singleLinkedList.add2(hero1);
        singleLinkedList.add2(hero2);
        singleLinkedList.add2(hero3);
        singleLinkedList.add2(hero4);
        singleLinkedList.list();

        HeroNode hero5 = new HeroNode(3, "吴用", "智多星");
        singleLinkedList.update(hero5);
        System.out.println("==========================");
        singleLinkedList.list();

        System.out.println("@@@@@@@@@@测试删除@@@@@@@@@@@");
        singleLinkedList.del(4);
        singleLinkedList.del(2);
        singleLinkedList.del(1);
        singleLinkedList.list();
        
        

    }

}

// 定义我们的单向链表管理Hero
class SingleLinkedList {
    // 先初始化一个头结点, 头结点一般不会动
    private HeroNode head = new HeroNode(0, "", "");

    // 删除节点
    // 1. 思路
    // 删除的思路
    // 1). head 不能动
    // 2). 使用temp变量, 我们要删除的应该是temp 的下一个结点., 即,我们在比较时,始终比较的是 temp.next 的节点值
    // 2. 代码
    public void del(int no) {
        HeroNode temp = head;
        boolean flag = false; // 标志变量用于确定是否有要删除的节点
        while (true) {
            if (temp.next == null) {
                break;
            }
            if (temp.next.no == no) {
                // 找到了
                flag = true;
                break;
            }
            temp = temp.next; // temp后移

        }

        if (flag) {
            // 可以删除
            temp.next = temp.next.next;

        } else {
            System.out.printf("要删除的no=%d 不存在\n", no);

        }
    }

    // 修改节点的值, 根据no编号为前提修改, 即no不能改
    // 课后思考题: 如果将这个节点替换,如何实现
    public void update(HeroNode newHeroNode) {
        if (head.next == null) {
            System.out.println("链表为空");
            return;
        }
        // 先找到节点
        HeroNode temp = head.next;
        boolean flag = false;
        while (true) {
            if (temp == null) {
                break;
            }
            if (temp.no == newHeroNode.no) {
                // 找到.
                flag = true;
                break;
            }
            temp = temp.next; //
        }

        // 判断是否找到
        if (flag) {
            temp.name = newHeroNode.name;
            temp.nickname = newHeroNode.nickname;
        } else {
            System.out.printf("没有找到 编号为%d 节点,不能修改\n", newHeroNode.no);
        }

    }

    // 编写添加方法
    // 第一种方法在添加英雄时,直接添加到链表的尾部
    public void add(HeroNode heroNode) {
        // 因为头结点不能动, 因此我们需要哟有一个临时结点,作为辅助
        HeroNode temp = head;
        // 找到链表的最后
        while (true) {
            if (temp.next == null) { // 说明temp已经是链表最后
                break;
            }
            // 如果没有到最后
            temp = temp.next;
        }

        // 当退出while循环后,temp就是链表的最后
        temp.next = heroNode;
    }

    // 第二种方式在添加英雄时,根据排名将英雄插入到指定位置
    // 如果有这个排名,则添加失败,并给出提示
    // 编号从小到大排序
    // 思路
    public void add2(HeroNode heroNode) {
        // 因为头结点不能动, 因此我们需要哟有一个临时结点,作为辅助
        // 注意,我们在找这个添加位置时,是将这个节点加入到temp的后面
        // 因此,在比较时,是将当前的heroNode 和 temp.next 比较
        HeroNode temp = head;
        boolean flag = false; // flag 是用于判断是否该英雄的编号已经存在, 默认为false
        while (true) {
            if (temp.next == null) { // 说明temp已经是链表最后
                break;
            }
            if (temp.next.no > heroNode.no) {
                // 位置找到,当前这个节点,应当加入到temp后
                break;
            } else if (temp.next.no == heroNode.no) {
                // 已经有这个节点
                flag = true;
                break;
            }
            temp = temp.next; // 注意
        }

        if (flag) { // 不可以加入
            System.out.printf("待插入的英雄编号 %d 已经有了,不能加入\n", heroNode.no);
        } else {
            // 加入,注意顺序
            heroNode.next = temp.next;
            temp.next = heroNode;
        }
    }

    // 遍历单向链表
    public void list() {
        // 判断当前链表是否为空
        if (head.next == null) {
            System.out.println("链表为空!!");
            return;
        }
        // 因为头结点不能动, 因此我们需要哟有一个临时结点,作为辅助
        // 因为head 结点数据,我们不关心,因此这里 temp=head.next
        HeroNode temp = head.next;

        while (true) {
            // 判断是否到最后
            if (temp == null) {
                break;
            }
            System.out.printf("结点信息 no=%d name=%s nickname=%s\n", temp.no, temp.name, temp.nickname);
            temp = temp.next;
        }

    }

}

// 先创建HeroNode
class HeroNode {
    public int no;
    public String name;
    public String nickname;
    public HeroNode next; // next 默认为null

    public HeroNode(int hNo, String hName, String hNickname) {
        no = hNo;
        name = hName;
        nickname = hNickname;
    }
}

//结束============================================

实现在单链表指定位置插入元素,并实现结点删除和修改

在数据1和数据4之间添加数据2:先让数据2的next域指向temp.next,也就是指向数据4,然后再让数据1的next域指向数据2。

修改节点思想:

删除节点思想:

 

 

 

 

//最新代码

package com.atguigu.temp.linkedlist

import util.control.Breaks._
object SingleLinkedListTest {
  def main(args: Array[String]): Unit = {
    //测试一下
    //创建HeroNode
    val hero1 = new HeroNode(1,"宋江","及时雨")
    val hero2 = new HeroNode(2,"宋江2","及时雨2")
    val hero3 = new HeroNode(4,"宋江4","及时雨4")
    val hero6 = new HeroNode(3,"宋江3","及时雨3")

    //创建
    val singleLinkedList = new SingleLinkedList
    singleLinkedList.add2(hero1)
    singleLinkedList.add2(hero2)
    singleLinkedList.add2(hero3)
    singleLinkedList.add2(hero6)

    singleLinkedList.list()

    //删除
    println("~~~~~~~~~~~~~~~~~~~~~~~~~~")
    //singleLinkedList.del(1)
    //singleLinkedList.del(2)
    //singleLinkedList.del(4)

    //singleLinkedList.list()

    //测试修改
//    println("===========修改===============")
//    val hero4 = new HeroNode(2,"吴用","智多星")
//    singleLinkedList.update(hero4)
//    //修改后
//    singleLinkedList.list()


  }
}

class SingleLinkedList {
  val head = new HeroNode(0, "", "")
  //添加方法, 方式1:
  def add(heroNode: HeroNode): Unit = {

    //head 是头结点,不用改变
    var temp = head
    breakable {
      while (true) {
        if (temp.next == null) {
          break()
        }
        temp = temp.next
      }
    }
    temp.next = heroNode
  }

  //安装编号的大小来插入
  def add2(heroNode: HeroNode): Unit = {

    //head 是头结点,不用改变
    var temp = head
    var flag = false // 表示是否已经存在
    breakable {
      while (true) {
        if (temp.next == null) {
          break() // 最后了
        }
        if (temp.next.no > heroNode.no) { //找到了
          break() //就应该插入到temp节点后面
        }
        if (temp.next.no == heroNode.no) { //已经有了
          flag = true
          break()
        }
        temp = temp.next
      }
    }
    if (!flag) { // 没有该节点, 可以添加
      heroNode.next = temp.next
      temp.next = heroNode
    } else {
      printf("你要添加的no=%d 的节点已经存在!\n", heroNode.no)
    }
  }

  //显示单链表
  def list(): Unit = {
    var temp = head.next
    breakable {
      while (true) {
        if (temp == null) {
          break()
        }
        printf("当前节点信息 no=%d name=%s nickname=%s\n",
          temp.no, temp.name, temp.nickName)
        temp = temp.next
      }
    }
  }

  //删除
  //思路:
  def del(no:Int): Unit = {
    var temp = head //要删除的是temp.next 节点,而不是temp节点,需要考虑单链表
    var flag = false

    breakable {
      while (true) {
        if (temp.next == null) {
          break()
        }
        if (temp.next.no == no) {
          //找到了
          flag = true
          break()
        }

        temp = temp.next
      }
    }

    if (flag) { //找到
      temp.next = temp.next.next
    }else{
      printf("你删除的no=%d 的节点不存在,无法删除\n", no)
    }
  }

  //修改, 给你一个新的node ,修改对应的值
  def update(newHeroNode:HeroNode): Unit = {

    var temp = head.next
    var flag = false
    //先找到这个节点
    breakable {
      while (true) {
        if (temp == null) {
          break()
        }
        if (temp.no == newHeroNode.no) {
          //找到了
          flag = true
          break()
        }
        temp = temp.next
      }
    }

    if (flag) { //找到
      temp.nickName = newHeroNode.nickName
      temp.name = newHeroNode.name
    }else{
      printf("你修改的no=%d 的节点不存在,无法修改\n", newHeroNode.no)
    }
  }

}

class HeroNode(hNo: Int, hName: String, hNickName: String) {
  var no: Int = hNo
  var name: String = hName
  var nickName: String = hNickName
  var next: HeroNode = null
 }

 

posted @ 2020-10-14 14:47  朱_煜  阅读(122)  评论(0编辑  收藏  举报