• 链表(Linked List): 单链表


    链表(Linked List)介绍

    链表是有序的列表,但是它在内存中是存储如下:

     小结:

    1. 链表是以节点的方式来存储,是链式存储。
    2. 每个节点包含 data域 , next域 : 指向下一个节点。
    3. 如图:发现链表的各个节点不一定是连续存储。
    4. 链表分带头节点的链表 和 没有带头节点的链表,根据实际的需求来确定。

    单链表介绍

    单链表(带头节点)逻辑结构示意图如下:

    •  单链表的应用实例

    使用带head头的单向链表实现—水浒英雄排行榜管理完成对英雄人物的增删改查操作。

    1)第一种方法在添加英雄时,直接添加到链表的尾部

    思路分析示意图:

    2)第二种方法在添加英雄时,根据排名将英雄插入到指定位置(如果有这个排名,则添加失败,并给出提示)

    思路分析示意图:

    3)修改节点的功能

    思路:

    ①先找到该节点,通过遍历 

    ②temp.name = newHeroNode.name; temp.nickname = newHeroNode.nickname;

    4)删除节点

    思路分析示意图:

    5)完整代码实现

      1 package com.jyj.linkedList;
      2 
      3 public class SingleLinkedListDemo {
      4     public static void main(String[] args) {
      5         //测试
      6         //先创建节点
      7         HeroNode hero1 = new HeroNode(1,"宋江","及时雨");
      8         HeroNode hero2 = new HeroNode(2,"卢俊义","玉麒麟");
      9         HeroNode hero3 = new HeroNode(3,"吴用","智多星");
     10         HeroNode hero4 = new HeroNode(4,"林冲","豹子头");
     11         
     12         //创建链表
     13         SingleLinkedList singleLinkedList = new SingleLinkedList();
     14         //加入
     15 //        singleLinkedList.add(hero1);
     16 //        singleLinkedList.add(hero4);
     17 //        singleLinkedList.add(hero2);
     18 //        singleLinkedList.add(hero3);
     19         
     20         //加入
     21         singleLinkedList.addByOrder(hero1);
     22         singleLinkedList.addByOrder(hero4);
     23         singleLinkedList.addByOrder(hero2);
     24         singleLinkedList.addByOrder(hero3);
     25         
     26         //显示
     27         singleLinkedList.list();
     28         
     29         singleLinkedList.update(new HeroNode(2,"小卢","玉麒麟~~~"));
     30         
     31         System.out.println("修正后:");
     32         //显示
     33         singleLinkedList.list();
     34         
     35         singleLinkedList.del(1);
     36         singleLinkedList.del(4);
     37         System.out.println("删除后:");
     38         //显示
     39         singleLinkedList.list();
     40         
     41     }
     42 }
     43 
     44 //定义SingleLinkedList 管理英雄
     45 class SingleLinkedList {
     46     //先初始化一个头节点,头节点不要动,不存放具体的数据
     47     private HeroNode head = new HeroNode(0,"","");
     48     
     49     //添加节点到单向链表
     50     //思路:当不考虑编号的顺序时
     51     //1.找到当前链表的最后节点
     52     //2.将最后这个节点的next 指向  新的节点
     53     public void add(HeroNode heroNode) {
     54         //因为head节点不能动,因此我们需要一个辅助节点 temp
     55         HeroNode temp = head;
     56         //遍历链表,找到最后
     57         while(true) {
     58             //找到链表的最后
     59             if(temp.next == null) {
     60                 break;
     61             }
     62             //如果没有找到最后,就将temp后移
     63             temp = temp.next;
     64         }
     65         //当退出while循环时,temp就指向了链表的最后
     66         //将最后这个节点的next 指向 新的节点
     67         temp.next = heroNode;
     68     }
     69     
     70     //添加英雄时,根据排名将英雄插入到指定位置
     71     //(如果有这个排名,则添加失败,并给出提示)
     72     public void addByOrder(HeroNode heroNode) {
     73         //因为头节点不能动,因此我们仍然通过一个辅助指针(变量)来帮助我们找到添加的位置,
     74         //因为单链表,我们找到的temp是位于 添加位置的第一个节点,否则插入不了
     75         HeroNode temp = head;
     76         boolean flag = false; //flag标志添加的编号是否存在,默认为false
     77         while(true) {
     78             if(temp.next == null) { //说明temp已经在链表的最后
     79                 break;
     80             }
     81             if(temp.next.no > heroNode.no) { //位置找到,就在temp的后面插入
     82                 break;
     83             }else if(temp.next.no == heroNode.no) { //说明将要添加的heroNode的编号已经存在
     84                 flag = true; //说明编号存在
     85                 break;
     86             }
     87             //后移,遍历当前链表
     88             temp = temp.next;
     89         }
     90         
     91         if(flag) {
     92             System.out.printf("编号 %d 已经存在,不能再添加~
    ",heroNode.no);
     93         }else {
     94             //插入到链表中,temp的后面
     95             heroNode.next = temp.next;
     96             temp.next = heroNode;
     97         }
     98     }
     99     
    100     //修改节点的信息,根据no编号来修改,即no编号不能改
    101     public void update(HeroNode newHeroNode) {
    102         //判空
    103         if(head.next == null) {
    104             System.out.println("链表为空");
    105             return;
    106         }
    107         //找到需要修改的节点,根据no编号
    108         //定义一个辅助变量
    109         HeroNode temp = head.next;
    110         boolean flag = false; //表示是否找到该节点
    111         while(true) {
    112             if(temp == null) {
    113                 break; //已经遍历完链表
    114             }
    115             if(temp.no == newHeroNode.no) {
    116                 //找到
    117                 flag = true;
    118                 break;
    119             }
    120             temp = temp.next;
    121         }
    122         //根据flag 判断是否找到要修改的节点
    123         if(flag) {
    124             temp.name = newHeroNode.name;
    125             temp.nickname = newHeroNode.nickname;
    126         }else { //没有找到
    127             System.out.printf("编号 %d 不存在,不能修改~",newHeroNode.no);
    128         }
    129     }
    130     
    131     //删除链表
    132     //思路
    133     //1.head 不能动,因此我们需要一个temp辅助节点找到待删除节点的前一个节点
    134     //2.说明我们在比较时,是 temp.next.no 和 需要删除的节点的no 比较
    135     public void del(int no) {
    136         //辅助链表
    137         HeroNode temp = head;
    138         boolean flag = false; //标志是否找到待删除的节点
    139         
    140         while(true) {
    141             if(temp.next == null) { //已经到链表最后
    142                 break;
    143             }
    144             if(temp.next.no == no) {
    145                 //找到待删除节点的前一个节点temp
    146                 flag = true;
    147                 break;
    148             }
    149             temp = temp.next; //后移
    150         }
    151         
    152         if(flag) {
    153             //删除节点
    154             temp.next = temp.next.next;
    155         }else {
    156             System.out.printf("要删除的 %d 节点不存在
    ",no);
    157         }
    158     }
    159     
    160     //显示链表[遍历]
    161     public void list(){
    162         //判断链表是否为空
    163         if(head.next == null) {
    164             System.out.println("链表为空");
    165             return;
    166         }
    167         //因为头节点不能动,因此需要辅助变量来遍历
    168         HeroNode temp = head.next;
    169         while(true) {
    170             //判断是否到链表最后:注意是temp == null,不是temp.next == null
    171             if(temp == null) {
    172                 break;
    173             }
    174             //输出节点的信息
    175             System.out.println(temp);
    176             //将temp 后移,不然就是死循环
    177             temp = temp.next;
    178         }
    179     }
    180 }
    181 
    182 //定义HeroNode,每个HeroNode 对象就是一个节点
    183 class HeroNode {
    184     public int no;
    185     public String name;
    186     public String nickname;
    187     public HeroNode next; //指向下一个节点
    188     
    189     //构造器
    190     public HeroNode(int no,String name,String nickname) {
    191         this.no = no;
    192         this.name = name;
    193         this.nickname = nickname;
    194     }
    195 
    196     //为了显示方便,重写toString
    197     @Override
    198     public String toString() {
    199         return "HeroNode [no=" + no + ", name=" + name + ", nickname="
    200                 + nickname + "]";
    201     }
    202 }
    View Code

    以上

    朱子家训说:宜未雨而筹谋,勿临渴而掘井。 任何事情要到了跟前才想解决办法,那我们岂不很被动!
  • 相关阅读:
    2016年之前优秀的单目SLAM系统
    EPSON四轴机械臂原点校准
    运动控制之手眼定位
    【已解决】移动端页面手势滑动触发touch 事件时,在左右上下部分出现空白部分的问题
    es分组排序和聚合后再筛选
    git配置ssh和小乌龟配置ssh
    单调栈的简单分享 Marathon
    es6.18升级到es7.17的不同点记录 Marathon
    input的ref属性
    手写axios
  • 原文地址:https://www.cnblogs.com/jianyingjie/p/12070518.html
Copyright © 2020-2023  润新知