前言

数据结构是计算机存储、组织数据的方式。如果不会数据结构,那么就不可能写出好的代码,因此。数据结构是我们学习编程不可或缺的一部分!链表是数据结构中的一种,但是链表又分为单向链表,双向链表,循环链表,本篇文章主要是聊聊链表中的单向链表。

单向链表(single-linked list)概述

一个单链表的节点(Node)分为两部分,第一个部分(data)保存或者显示关于节点的信息,另一个部分储存下一个节点的地址,最后一个节点的储存地址部分指向空值。

单向表只可向一个方向便利,一般查找一个节点的时候需要从第一个节点开始每次访问下一个节点,一直访问到需要的位置。而插入一个节点,对于单向链表,我们只提供在链表头插入,只需要将当前的节点设置为头节点,next指向源头节点即可。删除一个节点,我们将该节点的上一个的next指向下一个节点
单链表的原理及实现,你确定会吗?

算法分析:

链表中元素的增加(需要按照编号的顺序添加):

  1. 首先找到新添加的节点的位置, 是通过辅助变量(指针), 通过遍历来搞定
  2. (新的节点)heroNode.next = temp.next
  3. 将temp.next = heroNode.next(新的节点)

单链表的原理及实现,你确定会吗?

链表中元素的删除(需要按照编号进行删除):

  1. 我们先找到需要删除的这个节点的前一个节点 temp
  2. temp.next.no = herNode.next(temp.next.next)
  3. 被删除的节点,将不会有其它引用指向,会被垃圾回收机制回收
    单链表的原理及实现,你确定会吗?

    链表中元素的修改(需要按照编号进行删除):

    1、按照no找到要修改的编号
    2、temp.name=newHeroNode.name;
    3、temp.nickName=newHeroNode.nickName;

    注意事项:

    在创建、修改、删除中所创建的辅助变量temp都是必须的,因为head的值是不能变化的,一旦head发生变化,整个链表就会报错。

    代码实现:

public class SingleLinkedListDemo {

    public static void main(String[] args) {
        HeroNode hero1=new HeroNode(1, "宋江", "及时雨");
        HeroNode hero2=new HeroNode(2, "卢俊义", "玉麒麟");
        HeroNode hero3=new HeroNode(3, "吴用", "智多星");
        HeroNode hero4=new HeroNode(4, "林冲", "豹子头");
        SingleLinkedList singleLinkedList = new SingleLinkedList();
        //singleLinkedList.add(hero1);
        //singleLinkedList.add(hero2);
        //singleLinkedList.add(hero3);
        //singleLinkedList.add(hero4);
        singleLinkedList.addByOrder(hero1);
        singleLinkedList.addByOrder(hero4);
        singleLinkedList.addByOrder(hero2);
        singleLinkedList.addByOrder(hero3);
        singleLinkedList.addByOrder(hero3);
        System.out.println("修改前:");
        singleLinkedList.list();
        HeroNode newHeroNode =new HeroNode(2, "小卢", "小麒麟");
        singleLinkedList.update(newHeroNode);
        System.out.println("修改后:");
        singleLinkedList.list();
        singleLinkedList.delete(hero3);
        System.out.println("删除后:");
        singleLinkedList.list();
    }

}
class SingleLinkedList{
    //先初始化一个头结点,头结点不要动,不存放具体数据
    private HeroNode head = new HeroNode(0, "", "");
    public void add(HeroNode heroNode) {
        HeroNode temp = head;//定义一个辅助变量来存放head,因为head是不可变的
        //遍历链表,找到最后
        while(true) {
            if(temp.next==null) {
                break;//找到链表的最后一个之后。break
            }
            //如果没有找到,就将temp后移,当退除循环时,temp指向链表的最后
            temp = temp.next;
        }
        //temp指向新的节点
        temp.next = heroNode;
    }
    public void addByOrder(HeroNode heroNode) {
        HeroNode temp = head;
        //因为时单链表,因此我们要找的temp是位于插入节点前一个位置的否则插入不了
        boolean flag = false;//flag标志添加的编号是否存在,默认为false
        while(true) {
            if(temp.next==null)//temp已经再链表的最后,break
                break;
            if(temp.next.no>heroNode.no)//与添加位置的后一位no进行比较,位置已找到
                break;
            else if(temp.next.no==heroNode.no){//说明希望添加的heroNode的编号已经存在
                flag = true;
                break;
            }
            temp = temp.next;
        }
        if(flag == true) {
            System.out.printf("准备插入的这个英雄的编号%d已经存在,不能加入",heroNode.no);
            System.out.println();
        }
        else {
            //插入到链表中
            heroNode.next=temp.next;
            temp.next=heroNode;
        }
    }
    //修改节点的信息,no不能更改
    public void update(HeroNode newHeroNode) {
        if(head.next==null) {
            System.out.println("LinkedList为空");
            return;
        }
        HeroNode temp = head;
        boolean flag = false;
        while(true) {
            if(temp.next==null)//已经遍历完链表
                break;
            if(temp.no==newHeroNode.no)
            {
                flag = true;
                break;
            }
            temp = temp.next;
        }
        if(flag == true) {
            temp.name=newHeroNode.name;
            temp.nickName=newHeroNode.nickName;
        }
        else {
            System.out.printf("没有找到编号等于%d的节点",newHeroNode.no);
        }

    }
    public void delete(HeroNode heroNode) {
        if(head.next==null) {
            System.out.println("该链表为空,无法删除");
            return;
        }
        HeroNode temp = head;
        boolean flag = false;
        while(true) {
            if(temp.next==null)
                break;
            if(temp.next.no==heroNode.no) {
                flag = true;
                break;
            }
            temp = temp.next;
        }
        if(flag == true) {
            temp.next=heroNode.next;
        }
        else {
            System.out.printf("要删除的no为%d的节点不存在",heroNode.no);
        }
    }
    //显示链表(遍历)
    public void list() {
        //先判断链表是否为空
        if(head.next==null) {
            return;
        }
        //因为头节点不能动,因此需要一个辅助变量
        HeroNode temp = head.next;
        while(true) {
            if(temp==null) {
                break;
            }
            System.out.println(temp.toString());
            temp = temp.next;//后移
        }
    }
}
//定义一个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;
    }
    @Override
    public String toString() {
        return "HeroNode [no=" + no + ", name=" + name + ", nickName=" + nickName + "]";
    }

}