Java数据结构之单链表上

        上一篇呢,我们学习了使用数组模拟队列,大家都知道数据结构分为线性结构和非线性结构,线性结构呢,又有两种不同的存储结构,分别是 顺序存储结构(数组)链式存储结构(链表) ,今天我们就来学习链式存储结构中的单链表。

        顺序存储的线性表称为顺序表,顺序表中的存储元素是连续的链式存储的线性表称为链表,链表中的存储元素不一定是连续的,元素节点中存放数据元素以及相邻元素的地址信息。

        线性表的顺序存储 结构呢,它是有 缺点的,最大的缺点就是插入和删 除时需要移动大量元素,这显然就需要耗费时间。那么有没有一种解决方法呢?想要解决这个问题,我们就要知道问题的成因是什么:为什么当插入和删除时,就要移动大量元素,仔细分析后,发现原因就在于相邻两元素的存储位置也具有邻居关系。它们编号是1,2,3,…,n,它们在内存中的位置也是挨着的,中间没有空隙,当然就无法快速介入,而删除后,当中就会留出空隙,自然需要弥补。问题就出在这里。

        经过分析我们知道了,插入和删除时元素的原因是在内存中他们是相邻的,插入时中间没有间隙所以需要移动位置空出空隙,删除时中间又有了空隙,需要移动位置填补空隙。知道原因后,我们就发现问题原来是因为是挨着的,那我们是不是可以让所有元素都直接有空隙是不是更好,只要让元素知道他的下一个元素在哪里就ok了。这样,我们可以在第一个元素时,就知道第二个元素的位置(内存地址),而找到它;在第二个元素时,再找到第三个元素的位置(内存地址)。这样所有的元素我们就都可以通过遍历而找到。我超,这不就是线性表的链式存储结构(链表)吗?下面我们就来介绍一下线性表的链式存储结构(链表)。

        链表是有序的列表,但是它在内存中是存储如下(应该能看懂吧,图太难画了...)

         通过观察可知:

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

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

        下面我们来学习创建单链表,我们以英雄联盟英雄为例子来创建单链表。赋予四个属性。

分别是:编号、名字、昵称、指向下一个节点(没有的话则为空)。添加构造方法,重写toString方法。代码如下:

//定义HeroNode,每一个HeroNode对象就是一个节点
class HeroNode {
    public int no;//编号
    public String name;//名字
    public String nickname;//昵称
    public HeroNode next;//指向下一个节点 如果没有则为空

    public HeroNode() {
    }

    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 + '\'' +
                '}';
    }
}

        下面我们来添加英雄,我们使用两种办法来添加今天先演示第一种,直接加入链表后。(第二种根据编号顺序来添加)

思路:

1、先初始化一个head,head不动,不存放数据。(为什么要初始化head呢?因为整个链表的存取都要从head开始,head指向链表的第一个节点

1、找到当前链表的最后节点。(遍历查找)

2、将最后节点的next指向新的节点

由于头结点不能动所以我们需要一个辅助变量tmep,temp就是一个随着遍历而动的一个变量。

heroNode temp=head;如下图所示:(每遍历一个数据temp就往下跳一下)

 

 代码如下:

class SingleLinkedList {
    //先初始化一个头结点,头结点不动,不存放数据
    HeroNode head = new HeroNode();


    /**
     * 思路,当不考虑编号顺序时
     * 1、找到当前链表的最后节点
     * 2、将最后这个节点的next指向新的节点
     *
     * 第一种方式在添加英雄时,直接往后添加就ok
     */
    //添加节点到单链表
    public void add(HeroNode heroNode) {
        //因为head节点不能动,因此我们需要一个辅助变量temp
        HeroNode temp = head;
        //遍历链表,找到最后一个节点
        while (true) {
            //找到链表的最后
            if (temp.next == null) {
                break;
            }
            //没找到  temp往后移
            temp = temp.next;
        }
        //当退出循环时,temp就指向了链表的最后
        //将最后这个节点的next指向新的节点
        temp.next = heroNode;
    }
}

但是这样添加的话你加入的是什么顺序输出的就是什么顺序,第二种添加可以按照编号顺序添加,,如果这个编号的已存在也会提示该节点已存在,不过由于时间有限单链表的按照编号顺序添加以及修改删除遍历明天再写。

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值