链表原理及代码实现

一、链表(Linked List)是什么?

链表是一种有序列表,它的每一个数据以一个节点的形式存储,每个节点包括存储的数据(element)以及他的下一个节点的地址(next)。
在这里插入图片描述节点代码:

    class Node{
        Student element;
        Node next;

        public Node() {
        }

        public Node(Student element, Node next) {
            this.element = element;
            this.next = next;
        }
    }

链表虽然是有序列表,但是其在内存中并不一定是连续存储的! 如下图:
在这里插入图片描述

小结

  1. 链表是以节点的方式来存储的,是链式存储
  2. 每个节点包括数据以及下一节点地址
  3. 虽然链表是有序列表,但是并不一定是连续存储的

二、单链表的简单实现

该实现完成了对链表的创建,添加数据,删除数据,修改数据,查询数据是否存在,列出链表所有数据以及查询链表大小的功能
该链表主要用于存储学生对象,学生对象包含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());

    }
}

------------------------------------------------------------------------------------ 未完待续------------------------------------------------------------------------------------

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值