众所周知,数组和链表都有内存寻址的功能。而数组元素的内存地址是连续的,在寻址的时候很容易就可以找到下一个节点的值。
而链表中元素的地址不是连续的,那我们应该怎么去寻址呢?
假设现在计算机中有三个节点:5,6,2,这三个节点内存地址是不连续的。我们想要通过5找到6,通过6找到2,就需要在存储数据的同时将下一个节点的地址一并存进来,这样的话,我们就可以实现寻址的功能。这其实就是一个简单的链表(如下图)。
我们现在知道了链表的概念,那我们如何用java写一个单链表呢?
因为java没有自带链表,所以我们需要自己定义链表。
首先我们要知道,java中有栈内存,堆内存和方法区,那我们应当将这两个节点(数据和记录地址)存放在哪里呢?
如果把他们存储在栈内存中,这时候就会出现一个问题。因为数据并不能长久地存储在栈当中,所以当一个数据压入栈之后,栈会判断记录地址,如果记录地址为空,这时压入栈的数据会马上弹栈。这显然是不行的。
那把他们存储在方法区当中可以吗?
我们都知道,java文件在运行时,首先由编译器将其编译为class文件,然后class文件进入方法区开始执行。而只有static类型的数据才能放入方法区的常量池中。但是他们能做常量吗?显然是不能的 。
故综上所述,我们只能将他们存放在堆内存当中。
这时候就又会出现一个问题:数据和记录地址的数据类型是不同的,故我们不可以像数组那样将他们直接存放到堆内存当中。那现在怎么办呢?
如果我们在堆内存当中先建立一个对象,然后将链表存放在这个这个对象当中,是不是这个问题就被完美的解决了呢?
所以我们在对象当中建立一个类,将数据和记录地址当做变量,这样的话我们就将链表存储进了对象当中。
import java.util.List;
/**
* 当前节点类,在堆内存当中创建节点
*/
public class ListNode {
public int value; // 数据域
public ListNode next; // 下一个节点的地址域
public ListNode(int value){
this.value = value;
}
}
现在写一个主方法调用一下。
public class Test {
public static void main(String[] args) {
Node node = new Node(5);
Node node = new Node(6);
Node node = new Node(2);
}
}
这样的话一个简单的单链表就已经构建完成了。
但是像这样把链表数据的输入直接放在主函数当中我们是不好对链表进行维护和修改,这样用起来也不是很方便,所以就需要创建一个链表的管理类,让我们可以自由的控制链表并且输出他的值。
// 链表的管理类
public class LinkList {
ListNode head = null;
//写一个方法,创建链表(链表的插入)
//尾插法
public void insert(int value){
ListNode listNode = new ListNode(value);
if (head == null){
head = listNode;
return;
}
ListNode tempNode = head;
while (tempNode.next !=null){
tempNode = tempNode.next;
}
tempNode.next = listNode;
}
// 输出链表的值
public void printLink(){
//定义右边指向链表当中的第一个节点
ListNode tempNode = head;
while (tempNode !=null){
System.out.println(tempNode.value);
tempNode = tempNode.next;
}
}
}
现在再次写一个主方法调用一下。
public class Test {
public static void main(String[] args) {
LinkList linkList = new LinkList();
linkList.insert(5);
linkList.insert(7);
linkList.insert(8);
linkList.insert(9);
linkList.printLink();
}
}
这样的话,一个简单实用的单链表就创建完成啦。
上面在构建链表的时候我们使用的是尾插法,其实还有头插法。
//头插法
public void HeadAdd(int value){
ListNode listNode = new ListNode(value);
listNode.next = head;
head = listNode;
}
我们还可以定义函数输出链表的长度。
// 输出当前链表的长度
public void getLength(){
if (head ==null){
return;
}
ListNode tempNode = head;
int count = 0;
while (tempNode !=null){
count ++;
tempNode = tempNode.next;
}
System.out.println(count);
}
这就是单链表的基本概念及代码实现啦。