java循环单链表类构造函数_Java单链表的实现

最近在刷Leetcode时,遇到链表的题,想去测试运行结果,却发现Java中并没有单链表的实现;于是在网上搜索了如下两篇文章(参考文献),参考实现了一个简易的Java单链表:

/*** Definition for singly-linked list.

* public class ListNode {

* int val;

* ListNode next;

* ListNode() {}

* ListNode(int val) { this.val = val; }

* ListNode(int val, ListNode next) { this.val = val; this.next = next; }

* }*/

java的单链表的实现,在C语言中,链表的实现是用指针来实现的,也就是用指针来指向下一个节点的地址来实现链表。

当然,Java内部也有自己的链表--LinkedList,双向链表,优点,增加删除,用时间很短,但是因为没有索引,对索引的操作,比较麻烦,只能循环遍历;

但是每次循环的时候,都会先判断一下,这个索引位于链表的前部分还是后部分,每次都会遍历链表的一半 ,而不是全部遍历(不太理解这句话,有同学能帮解释下么???)。

双向链表,都有一个previous和next, 链表最开始的部分都有一个fiest和last 指向第一个元素,和最后一个元素。

增加和删除的时候,只需要更改一个previous和next,就可以实现增加和删除,所以说,LinkedList对于数据的删除和增加相当的方便。

但是我们今天不是讨论LinkedList,而是自己来实现一个单链表,包括简单的增删查改:

单链表的结构

单链表的基本操作

虚拟头结点的使用

整个类的设计如下:

public class Linked {public class Node{privateE element;privateNode next;publicNode() {}publicNode(E element, Node next){this.element =element;this.next =next;

}publicNode(E element){this(element, null);

}

}private Node head; //头结点

private int size; //链表元素个数//构造函数

publicLinked(){this.head = null;this.size = 0;

}

}

那在java中没有指针的这个概念,我们应该怎么实现,怎么来表示地址,怎么指向一个地址;

我们来看一个例子:

Student stu=new Student();

那,我们知道这行代码是一个对象的实例化,那这行代码到底是什么意思呢?

我们这样理解:stu这个变量存储在栈内存中,右边的new Student()存储在堆内存中,就像这样:

e07c5dde4691ddff8d7e71538e405fc5.png

也就是可以这样理解,左边变量的值,就是右边的地址,也就是左边的变量指向了右边的地址;

所以在我后面写的一些代码,就可以理解成等号左边是变量,右边是地址!

OK,现在我们来说链表,要想实现一个链表,自然少不了节点,那么一个节点应该有什么呢?

和C语言一样,应该有数据项和指向下一个节点的对象。那在C中有结构体这么一说可以来实现这样一个节点,在JAVA中呢,就是类,也就是实现出一个节点类!

单链表的结构

一种链式存取的数据结构,单链表中的数据是以结点的形式存在,每一个结点是由数据元素和下一个结点的存储的位置组成。单链表与数组相比的最大差别是:单链表的数据元素存放在内存空间的地址是不连续的,而数组的数据元素存放的地址在内存空间中是连续的,这也是为什么根据索引无法像数组那样直接就能查询到数据元素。

adb7c1f4f713f3143d0051c13365854f.png

[单链表结构图]

一、链表存储的节点(节点类的实现)

public class Node{privateE element;privateNode next;publicNode() {}publicNode(E element, Node next){this.element =element;this.next =next;

}publicNode(E element){this(element, null);

}

}

类中应该有一个next的对象来指向下一个节点,还要有一个element来存储数据,加了一个泛型来表示数据类型!

在构造方法中我们应该有两个参数,一个是节点的数据,还有就是指向下一个节点的next;

有了这个节点类,我们就可以创建出一个链表类:Linked

public class Lisked{}

那链表类中应该有什么成员变量呢:是不是应该有一个头结点head,这个头节点应该是Node类型,还要有一个size来记录节点的个数:

private Node head; //头结点

private int size; //链表元素个数

二、获取节点的方法(链表的基本操作)

然后我们思考一个问题,是不是我们在进行指定位置添加元素,指定位置删除元素,指定位置修改元素,我们都要通过一个索引(我只是说索引,但在链表是没有索引这一个概念的,索引的概念只在数组中出现,但为了方便叙述,就不要纠正我了哈)来操作这个链表,那么我不想在每个方法中都写一遍,我就可以拿出来这么一个方法,实现通过索引查找元素的方法:

这个方法的返回值,应该就是Node类型的节点。

我们举例子来说:

0a1460744878c95818670032fe0d2dad.png

看,我们要拿到第三个节点,是不是应该就是head的下一个的下一个,那下一个在节点类中是不是就是next!

在构造方法中我们应该有两个参数,一个是节点的数据,还有就是指向下一个节点的next;第三个元素是不是就可以写成head.next.next!这是不是就是通过索引来遍历:

来看代码:

private Node node(intindex){

Node x=head;for(int i=0;i

x=x.next;

}returnx;

}

我每次都让x=x的下一个,起到了查找的遍历方法!

三、指定位置添加元素(链表结点的增加)

现在我们有了这个node方法,我们来写一下指定位置添加元素:

public void add(int index,E element){}

函数里面应该怎么写呢,我们先考虑第一种情况,添加第一个元素,也就是index==0的情况:

我在最开始没有添加的时候,只应该有一个节点first吧:

c9cdb28b13c426073c73347dc274cff9.png

并且他的next应该是指向空的;

那我们现在要通过add(0,E element)添加一个节点,那我是不是就要new出来一个节点

new Node(null,element)

be79086cd2b331e48cf146f485a0673c.png

next为空,对吧,现在两个节点出来了,我们要把他们两个连起来:

那first的next就不应该为空,而是指向这个新节点!

286df06704219db7e7723758be1a8baa.png

这回再想一下我文章开头说的话,实现这一步应该怎么做?

if(index==0) {

first=new Node(null,element);

}

是不是就这一行代码就可以了,等号左边是变量,右边是地址,把他写进add方法中!

然后我们在考虑index不为0的情况怎么写。

9c089a7fef51c4c5cf80bd7c1649a3ed.png

如果我们想在3这个位置添加一个节点:

b24cd03c07f97e68a1dc735c4f2a200f.png

我们是不是要获取到第二个和第三个这两节点,对吧,因为要在这两个节点中插入嘛,所以一定要获取这两个节点,用什么方法,node啊!

Node pre=node(index-1);

Node next=pre.next;

这两个节点获取到了怎么办,我是不是应该要新new出来一个节点,然后这个new节点的next要指向3这个位置!

new Node(next,element)

是不是这样(看参数!);

然后呢,再让2这个节点,指向这个new节点,是不是就完事了!

pre.next=new Node(next,element);

最后一步再让size++,并且判断一下index的索引是否越界,是不是就可以了!

最后再看一下完整的代码:

转载/参考文献:

1. https://blog.csdn.net/weixin_36605200/article/details/88804537

2. https://blog.csdn.net/weixin_46726346/article/details/107687955

3. https://blog.csdn.net/qq_32575047/article/details/78885066

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值