文章目录
一、链表(Linked List)是什么?
链表是一种有序列表,它的每一个数据以一个节点的形式存储,每个节点包括存储的数据(element)以及他的下一个节点的地址(next)。
节点代码:
class Node{
Student element;
Node next;
public Node() {
}
public Node(Student element, Node next) {
this.element = element;
this.next = next;
}
}
链表虽然是有序列表,但是其在内存中并不一定是连续存储的! 如下图:
小结
- 链表是以节点的方式来存储的,是链式存储
- 每个节点包括数据以及下一节点地址
- 虽然链表是有序列表,但是并不一定是连续存储的
二、单链表的简单实现
该实现完成了对链表的创建,添加数据,删除数据,修改数据,查询数据是否存在,列出链表所有数据以及查询链表大小的功能
该链表主要用于存储学生对象,学生对象包含id,name,age三个成员变量,并提供空参构造,满参构造,geter和seter方法,并重写了
toString()方法。
学生对象代码如下:
package linked.singlelinked;
/**
* @author Eleven
* @version V1.0
* @package: linked.singlelinked
* @date 2021-10-26 17:15
*/
public class Student {
private String id;
private String name;
private int age;
public Student() {
}
public Student(String id, String name, int age) {
this.id = id;
this.name = name;
this.age = age;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Student{" +
"id='" + id + '\'' +
", name='" + name + '\'' +
", age=" + age +
'}';
}
}
功能分析
添加
本次链表实现了两种添加方式
方式一:直接添加到链表尾部
实现分析:
因为链表在内存中存储不一定是连续的,所有添加操作需要遍历所有的数据找到链表尾部,即当节点的next为空时,即为链表尾部
由于头部是不能动的,所以我们需要定义一个临时节点(temp)来作为指针遍历数组。
其实现代码如下
/**
* 向链表中添加元素
* 创建时间:2021/10/25 23:20
* @author Eleven
* @param student 需要添加的元素
*/
public void add(Student student){
Node temp = head;//head为链表头部节点,其不包含数据,head.next为第一个包含学生数据的节点
while (true){
if(temp.next == null){
temp.next = new Node(student, null);
size++;//记录现在链表的大小
break;
}
temp = temp.next;
}
}
方法二:根据ID排序添加
因为要按学生学号的大小进行添加,因此后续添加的数据大概率是插入原有数据之间
在添加数据时需要遍历所有数据并比较它们的id大小。与直接添加至链表尾部的方式一样,头部不能动,我们需要借助一个临时节点(temp)来遍历数组,但是,遍历时比较id不是用temp指向的元素的id与新添元素的id进行比较,而是用temp.next节点的id与新添元素进行比较,当发现temp.next.element.getId().compareTo(student.getId()) > 0
时,新添的数据就找到了正确的位置。
当发现ID相同时,抛出异常。
其实现代码如下
/**
* 按id顺序添加学生
* 创建时间:2021/10/26 19:12
* @author Eleven
* @param student 要添加的学生
*/
public void addByOrder(Student student){
Node temp = head;
while (true){
//已经遍历到链表尾部,已有数据任然没有id大于新添数据id的,即该新添数据应放到链表尾部
if(temp.next == null) break;
//temp指向节点的下一个节点的id大于新添数据id,新添数据因放在temp后面
if(temp.next.element.getId().compareTo(student.getId()) > 0)
break;
if(temp.next.element.getId().compareTo(student.getId()) == 0)
throw new RuntimeException("该学号已存在!!");
temp = temp.next;
}
//放置新添数据到temp后面,并将原来temp后的数据链接至新添数据后
temp.next = new Node(student, temp.next);
size++;//更新链表大小
}
查询
查询数据通过遍历整个链表实现,具体代码如下
查询代码为:
/**
* 查询指定id的元素是否存在
* 创建时间:2021/10/26 13:54
* @author Eleven
* @param id 要查找的学生的id
* @return 若存在返回该元素,若不存在返回null
*/
public Node findValue(String id){
if(isEmpty()) throw new RuntimeException("链表为空!");
Node node = find(id);
if(node != null){
return node.next;
}else {
throw new RuntimeException("该元素不存在!");
}
}
由于删除和修改都需要找到需要删除/修改的数据的位置,这里提供一个内部方法来查找指定元素位置,不过,该方法返回的是指定元素的前一个节点。
实现代码如下:
/**
* 查找元素并返回该元素的前一个节点
* 创建时间:2021/10/26 12:48
* @author Eleven
* @param id 要查找的学生的id
* @return 返回查找到元素的前一个节点,若未找到返回null
*/
private Node find(String id){
Node temp = head;
boolean flag = false;
while (true){
//遍历完链表未找到元素
if(temp.next == null) break;
//找到要删除的元素
if( id.equals(temp.next.element.getId()) ) {
flag = true;
break;
}
temp = temp.next;
}
if(flag){
return temp;
}else {
return null;
}
}
删除
链表的删除就是将要删除的元素的前一个节点的next指向要删除元素的next,那么要删除的元素将没有任何节点指向他,就变成了垃圾,在下一次虚拟机的垃圾回收器回收时将进行清理。在下一次遍历的时候,就会直接跳过已删除的元素,即完成了删除
删除代码如下:
/**
* 删除指定元素
* 创建时间:2021/10/25 23:31
* @author Eleven
* @param id 要删除的学生的id
*/
public void remove(String id){
if(isEmpty()) throw new RuntimeException("链表为空!");
Node temp = find(id);
if(temp != null){
temp.next = temp.next.next;
size--;//更新链表大小
}else {
throw new RuntimeException("该元素不存在!");
}
}
修改
通过私有方法find找到需要修改的数据位置,对其进行修改
修改数据代码如下:
/**
*
* 创建时间:2021/10/26 12:38
* @author Eleven
* @param id 需要修改的数据
* @param filed 想要修改的属性
* @param value 修改后的新值
*/
public void modify(String id, String filed, String value){
if(isEmpty()) throw new RuntimeException("链表为空!");
Node temp = find(id);
if(temp != null){
if("id".equals(filed)){
throw new RuntimeException("id不可修改!");
}else if("name".equals(filed)){
temp.next.element.setName(value);
}else if("age".equals(filed)){
temp.next.element.setAge(Integer.parseInt(value));
}else {
throw new RuntimeException("请输入正确的属性");
}
}else {
throw new RuntimeException("该元素不存在!");
}
}
遍历链表
/**
* 遍历链表中所有数据
* 创建时间:2021/10/26 13:30
* @author Eleven
*/
public void list(){
if(isEmpty()) throw new RuntimeException("链表为空!");
Node temp = head;
while (true){
if(temp.next == null)
break;
temp = temp.next;
System.out.println(temp.element);
}
}
反转链表
由于是单链表,所有遍历链表只能从前往后,无法直接从后往前遍历实现反转。
这里我们定义一个新的头部(newHead),然后遍历原来的链表,每次从原链表取一个节点,接入新头部的链表的最前方,当遍历完成后,原链表头部的next指向新头部的next,即完成链表反转。
这个过程就像将右手的牌倒到左手一样,每次都取右手牌的第一张,放到左手牌的第一张,当牌全部都到左手后,再直接将左手的牌放回右手,那么右手的牌就完成了一次反转。
反转代码如下:
/**
* 反转链表
* 创建时间:2021/10/26 14:58
* @author Eleven
*/
public void revers(){
if(head.next == null || head.next.next == null) return;
Node newHead = new Node();
Node cur = head.next;
Node next = null;
while (cur != null){
next = cur.next;
cur.next = newHead.next;
newHead.next = cur;
cur = next;
}
head.next = newHead.next;
}
判断链表是否为空
前面的许多方法中都需要判断这个链表是否为空,这里提供方法进行判断
当链表的head.next == null
时,认为链表为空,实现代码如下:
/**
* 判断链表是否为空
* 创建时间:2021/10/25 23:22
* @author Eleven
*/
private boolean isEmpty(){
return head.next == null;
}
完整代码
package linked.singlelinked;
/**
* @author Eleven
* @version V1.0
* @package: linked.singlelinked
* @date 2021-10-25 23:03
*/
public class SingleLinkedDemo{
//链表大小
private int size = 0;
//头节点
Node head = new Node();
public SingleLinkedDemo() {
}
/**
* 向链表中添加元素
* 创建时间:2021/10/25 23:20
* @author Eleven
* @param student 需要添加的元素
*/
public void add(Student student){
Node temp = head;
while (true){
if(temp.next == null){
temp.next = new Node(student, null);
size++;
break;
}
temp = temp.next;
}
}
/**
* 按id顺序添加学生
* 创建时间:2021/10/26 19:12
* @author Eleven
* @param student 要添加的学生
*/
public void addByOrder(Student student){
Node temp = head;
while (true){
if(temp.next == null) break;
if(temp.next.element.getId().compareTo(student.getId()) > 0){
break;
}
if(temp.next.element.getId().compareTo(student.getId()) == 0)
throw new RuntimeException("该学号已存在!!");
temp = temp.next;
}
temp.next = new Node(student, temp.next);
size++;
}
/**
* 删除指定元素
* 创建时间:2021/10/25 23:31
* @author Eleven
* @param id 要删除的学生的id
*/
public void remove(String id){
if(isEmpty()) throw new RuntimeException("链表为空!");
Node temp = find(id);
if(temp != null){
temp.next = temp.next.next;
size--;
}else {
throw new RuntimeException("该元素不存在!");
}
}
/**
*
* 创建时间:2021/10/26 12:38
* @author Eleven
* @param id 需要修改的数据
* @param filed 想要修改的属性
* @param value 修改后的新值
*/
public void modify(String id, String filed, String value){
if(isEmpty()) throw new RuntimeException("链表为空!");
Node temp = find(id);
if(temp != null){
if("id".equals(filed)){
throw new RuntimeException("id不可修改!");
}else if("name".equals(filed)){
temp.next.element.setName(value);
}else if("age".equals(filed)){
temp.next.element.setAge(Integer.parseInt(value));
}else {
throw new RuntimeException("请输入正确的属性");
}
}else {
throw new RuntimeException("该元素不存在!");
}
}
/**
* 查询指定元素是否存在
* 创建时间:2021/10/26 13:54
* @author Eleven
* @param id 要查找的学生的id
* @return 若存在返回该元素,若不存在返回null
*/
public Node findValue(String id){
if(isEmpty()) throw new RuntimeException("链表为空!");
Node node = find(id);
if(node != null){
return node.next;
}else {
throw new RuntimeException("该元素不存在!");
}
}
/**
* 查找元素并返回该元素的前一个节点
* 创建时间:2021/10/26 12:48
* @author Eleven
* @param id 要查找的学生的id
* @return 返回查找到元素的前一个节点,若未找到返回null
*/
private Node find(String id){
Node temp = head;
boolean flag = false;
while (true){
//遍历完链表未找到元素
if(temp.next == null) break;
//找到要删除的元素
if( id.equals(temp.next.element.getId()) ) {
flag = true;
break;
}
temp = temp.next;
}
if(flag){
return temp;
}else {
return null;
}
}
/**
* 遍历链表中所有数据
* 创建时间:2021/10/26 13:30
* @author Eleven
*/
public void list(){
if(isEmpty()) throw new RuntimeException("链表为空!");
Node temp = head;
while (true){
if(temp.next == null)
break;
temp = temp.next;
System.out.println(temp.element);
}
}
/**
* 查询当前数据个数
* 创建时间:2021/10/26 14:36
* @author Eleven
* @return 返回当前链表的数据个数
*/
public int getSize(){
return size;
}
/**
* 反转链表
* 创建时间:2021/10/26 14:58
* @author Eleven
*/
public void revers(){
if(head.next == null || head.next.next == null) return;
Node newHead = new Node();
Node cur = head.next;
Node next = null;
while (cur != null){
next = cur.next;
cur.next = newHead.next;
newHead.next = cur;
cur = next;
}
head.next = newHead.next;
}
/**
* 判断链表是否为空
* 创建时间:2021/10/25 23:22
* @author Eleven
*/
private boolean isEmpty(){
return head.next == null;
}
class Node{
Student element;
Node next;
public Node() {
}
public Node(Student element, Node next) {
this.element = element;
this.next = next;
}
}
}
测试代码
package linked.singlelinked;
/**
* @author Eleven
* @version V1.0
* @package: linked.singlelinked
* @date 2021-10-26 12:50
*/
public class SingleLinkedTest {
public static void main(String[] args) {
SingleLinkedDemo sld = new SingleLinkedDemo();
Student student1 = new Student("001","张三",23);
Student student2 = new Student("002","李四",24);
Student student3 = new Student("003","王五",25);
Student student4 = new Student("004","赵六",26);
//测试添加方法
// sld.add(student1);
// sld.add(student2);
// sld.add(student3);
// sld.add(student4);
//测试按id排序添加方法
sld.addByOrder(student1);
sld.addByOrder(student4);
sld.addByOrder(student3);
sld.addByOrder(student2);
//测试id排序中存在相同id方法
try {
sld.addByOrder(student1);
} catch (Exception e) {
System.out.println(e.getMessage());
}
//测试遍历链表数据方法
sld.list();
System.out.println("-------------------------");
//测试删除方法
sld.remove("002");
sld.list();
System.out.println("-------------------------");
//测试修改方法
sld.modify("003","age", "18");
sld.list();
System.out.println("-------------------------");
//测试反转方法
sld.revers();
sld.list();
System.out.println("-------------------------");
//测试获取链表大小方法
System.out.println("链表当前大小为:" + sld.getSize());
}
}
三、双向链表的简单实现
由于单向链表的查找只能从头至尾一个方向,而且单向链表在进行操作时不能进行自我删除,需要依靠辅助节点来进行,所以单向列表在删除之前找到的节点总是待删除节点之前的节点。然而双向链表既可以从头至尾遍历也可以从尾至头进行遍历,而且进行操作时,可以进行自我删除,因此对上述单链表进行改进。
节点结构
首先,双向链表的节点结构发生了变化,之前的节点只包括要存储的数据本身和下一个节点的地址,双向链表的节点包括三个数据:前一个节点的地址(pre)、本节点存储的数据(element)、下一个节点的地址(next),其结构如下图
其存储示意图如下:
节点代码为:
class Node{
Student element;
Node pre;
Node next;
public Node() { }
public Node(Student element, Node pre, Node next) {
this.element = element;
this.pre = pre;
this.next = next;
}
}
功能分析
实现的功能只有添加与删除发生了比较大的变动,本节主要对这两个方法进行分析,其他功能仅提供代码,不再分析,其实现原理与单链表基本相同。
在实现类中定义了三个成员变量:size 、head、rear。
size:记录链表大小
head:指向链表头部
rear:指向链表尾部
添加
双向链表已实现了两种添加方法:直接至尾部和排序添加
方法一:直接添加到链表尾部
由于双向链表实现类中定义了指向尾部的变量,因此,直接添加变得很方便,将需要添加的数据封装到节点中,赋值给rear.next,然后将新节点的pre指向原来的rear,最后更新rear,将其指向新的尾部,添加完成。
若是第一次链表的第一次添加,则需新建一个节点,将pre与next都置为null,并将head和rear都指向该节点,完成添加操作。
其代码如下:
/**
* 向链表中添加元素
* 创建时间:2021/10/26 20:40
* @author Eleven
* @param student 需要添加的元素
*/
public void add(Student student){
//当本次添加为第一次添加时
if(head == null && rear == null){
head = rear = new Node(student,null, null);
size++;
return;
}
//将新添数据放到链表最后,并更新尾部
//new Node(student, rear , null);新建一个节点,并将该节点的pre指向原来的尾部
//rear.next = new Node(student, rear , null); 将原来的尾部指向新添加的节点
//rear = rear.next 更新rear指向最新的尾部
rear = rear.next = new Node(student, rear , null);
size++;
}
方法二:根据ID排序添加
若是第一次添加,其添加流程与方法一第一次添加流程相同
若不是第一次添加,需要先进行遍历比较id直到找到新添数据的正确位置。找到正确位置后,新建一个节点,将数据保证进该节点,并让其pre指向temp之前pre指向的节点,其rear指向temp,然后将之前指向temp的元素指向新建节点,最后更新temp的pre,将其指向新建节点,完成添加操作。
其代码如下:
/**
* 按id顺序添加学生
* 创建时间:2021/10/26 23:13
* @author Eleven
* @param student 要添加的学生
*/
public void addByOrder(Student student){
//当本次添加为第一次添加时
if(head == null && rear == null){
head = rear = new Node(student,null, null);
size++;
return;
}
//找到新数据应该添加的位置
Node temp = head;
boolean flag = false;
while (true){
if(temp == null) {
flag = true;
break;
}
if(temp.element.getId().compareTo(student.getId()) > 0){
break;
}
if(temp.element.getId().compareTo(student.getId()) == 0)
throw new RuntimeException("该学号已存在!!");
temp = temp.next;
}
if(flag){
//未找到id比新添元素的id大的元素,新添元素将放在链表最后,并将rear指向最新的尾部
rear = rear.next = new Node(student, rear , null);
}else {
//将新添加的数据放至temp之前
//new Node(student,temp.pre,temp);
//新建一个节点,其pre指向temp之前pre指向的节点,其rear指向temp
// temp.pre.next = new Node(student,temp.pre,temp);
//将temp之前的元素指向新建节点
temp.pre.next = new Node(student,temp.pre,temp);
//更新temp的pre,将其指向新建节点
temp.pre = temp.pre.next;
}
size++;
}
删除
双向链表的删除与单链表相比更简单,先查找到要删除的数据所在位置,然后将它前一个节点的next指向它的后一个节点,将它后一个节点的pre指向它的前一个节点即可完成删除操作。
其代码如下
/**
* 删除指定id的元素
* 创建时间:2021/10/26 21:41
* @author Eleven
* @param id 要删除的学生的id
*/
public void remove(String id){
if(isEmpty()) throw new RuntimeException("链表为空!");
Node temp = find(id);
if(temp != null){
//将temp前的节点指向temp后的节点
temp.pre.next = temp.next;
//将temp后的节点指向temp前的节点
temp.next.pre = temp.pre;
size--;
}else {
throw new RuntimeException("该元素不存在!");
}
}
完整代码
package linked.doublelinked;
import linked.singlelinked.SingleLinkedDemo;
import linked.singlelinked.Student;
/**
* @author Eleven
* @version V1.0
* @package: linked.doublelinked
* @date 2021-10-26 20:27
*/
public class DoubleLinkedDemo {
//链表大小
private int size = 0;
//头节点
Node head;
//尾节点
Node rear;
public DoubleLinkedDemo() { }
/**
* 向链表中添加元素
* 创建时间:2021/10/26 20:40
* @author Eleven
* @param student 需要添加的元素
*/
public void add(Student student){
//当本次添加为第一次添加时
if(head == null && rear == null){
head = rear = new Node(student,null, null);
size++;
return;
}
//将新添数据放到链表最后,并更新尾部
//new Node(student, rear , null);新建一个节点,并将该节点的pre指向原来的尾部
//rear.next = new Node(student, rear , null); 将原来的尾部指向新添加的节点
//rear = rear.next 更新rear指向最新的尾部
rear = rear.next = new Node(student, rear , null);
size++;
}
/**
* 按id顺序添加学生
* 创建时间:2021/10/26 23:13
* @author Eleven
* @param student 要添加的学生
*/
public void addByOrder(Student student){
//当本次添加为第一次添加时
if(head == null && rear == null){
head = rear = new Node(student,null, null);
size++;
return;
}
//找到新数据应该添加的位置
Node temp = head;
boolean flag = false;
while (true){
if(temp == null) {
flag = true;
break;
}
if(temp.element.getId().compareTo(student.getId()) > 0){
break;
}
if(temp.element.getId().compareTo(student.getId()) == 0)
throw new RuntimeException("该学号已存在!!");
temp = temp.next;
}
if(flag){
//未找到id比新添元素的id大的元素,新添元素将放在链表最后,并将rear指向最新的尾部
rear = rear.next = new Node(student, rear , null);
}else {
if (temp.pre != null) {
//将新添加的数据放至temp之前
//new Node(student,temp.pre,temp);
//新建一个节点,其pre指向temp之前pre指向的节点,其next指向temp
// temp.pre.next = new Node(student,temp.pre,temp);
//将temp之前的元素指向新建节点
temp.pre.next = new Node(student,temp.pre,temp);
//更新temp的pre,将其指向新建节点
temp.pre = temp.pre.next;
}else {
//若新添加的数据应该放到链表的头部位置
// new Node(student,null,temp);
//新建一个节点,将next指向temp
//temp.pre = new Node(student,null,temp);
//更新temp的pre,将其指向新建节点
//head = temp.pre 更新头结点
head = temp.pre = new Node(student,null,temp);
}
}
size++;
}
/**
* 删除指定id的元素
* 创建时间:2021/10/26 21:41
* @author Eleven
* @param id 要删除的学生的id
*/
public void remove(String id){
if(isEmpty()) throw new RuntimeException("链表为空!");
Node temp = find(id);
if(temp != null){
//将temp前的节点指向temp后的节点
temp.pre.next = temp.next;
//将temp后的节点指向temp前的节点
temp.next.pre = temp.pre;
size--;
}else {
throw new RuntimeException("该元素不存在!");
}
}
/**
*
* 创建时间:2021/10/26 12:38
* @author Eleven
* @param id 需要修改的数据
* @param filed 想要修改的属性
* @param value 修改后的新值
*/
public void modify(String id, String filed, String value){
if(isEmpty()) throw new RuntimeException("链表为空!");
Node temp = find(id);
if(temp != null){
if("id".equals(filed)){
throw new RuntimeException("id不可修改!");
}else if("name".equals(filed)){
temp.element.setName(value);
}else if("age".equals(filed)){
temp.element.setAge(Integer.parseInt(value));
}else {
throw new RuntimeException("请输入正确的属性");
}
}else {
throw new RuntimeException("该元素不存在!");
}
}
/**
* 查询指定元素是否存在
* 创建时间:2021/10/26 13:54
* @author Eleven
* @param id 要查找的学生的id
* @return 若存在返回该元素,若不存在返回null
*/
public Node findValue(String id){
if(isEmpty()) throw new RuntimeException("链表为空!");
Node node = find(id);
if(node != null){
return node;
}else {
throw new RuntimeException("该元素不存在!");
}
}
/**
*
* 创建时间:2021/10/26 21:33
* @author Eleven
* @param id 要查找的学生的id
* @return 返回查找到的数据,若未找到返回null
*/
private Node find(String id){
Node temp = head;
boolean flag = false;
while (true){
//遍历完链表未找到元素
if(temp == null) break;
//找到要删除的元素
if( id.equals(temp.element.getId()) ) {
flag = true;
break;
}
temp = temp.next;
}
if(flag){
return temp;
}else {
return null;
}
}
/**
* 遍历链表中所有数据
* 创建时间:2021/10/26 13:30
* @author Eleven
*/
public void list(){
if(isEmpty()) throw new RuntimeException("链表为空!");
Node temp = head;
while (temp != null){
System.out.println(temp.element);
temp = temp.next;
}
}
/**
* 查询当前数据个数
* 创建时间:2021/10/26 14:36
* @author Eleven
* @return 返回当前链表的数据个数
*/
public int getSize(){
return size;
}
/**
* 判断链表是否为空
* 创建时间:2021/10/26 20:43
* @author Eleven
*/
private boolean isEmpty(){
return head == null && rear == null;
}
class Node{
Student element;
Node pre;
Node next;
public Node() { }
public Node(Student element, Node pre, Node next) {
this.element = element;
this.pre = pre;
this.next = next;
}
}
}
测试代码
package linked.doublelinked;
import linked.singlelinked.Student;
import org.junit.Before;
/**
* @author Eleven
* @version V1.0
* @package: linked.doublelinked
* @date 2021-10-26 20:41
*/
public class DoubleLinkedTest {
public static void main(String[] args) {
DoubleLinkedDemo dld = new DoubleLinkedDemo();
Student student1 = new Student("001","张三",23);
Student student2 = new Student("002","李四",24);
Student student3 = new Student("003","王五",25);
Student student4 = new Student("004","赵六",26);
// dld.add(student1);
// dld.add(student2);
// dld.add(student3);
// dld.add(student4);
//测试按id排序添加方法
dld.addByOrder(student4);
dld.addByOrder(student1);
dld.addByOrder(student3);
dld.addByOrder(student2);
//测试id排序中存在相同id方法
try {
dld.addByOrder(student1);
} catch (Exception e) {
System.out.println(e.getMessage());
}
//测试遍历
dld.list();
System.out.println("------------------------");
//测试删除
dld.remove("002");
dld.list();
System.out.println("------------------------");
//测试修改方法
dld.modify("003","age", "18");
dld.list();
System.out.println("-------------------------");
//测试获取链表大小方法
System.out.println("链表当前大小为:" + dld.getSize());
}
}
------------------------------------------------------------------------------------ 未完待续------------------------------------------------------------------------------------