链表的定义与实现(Java)

什么是链表?

链表(Linked List)是一种常见的数据结构,用于存储数据的集合。与数组不同,链表中的数据元素不是按照线性顺序存储的,而是通过指针相互连接来组织的。

链表由一系列节点组成,每个节点包含两部分:数据和指向下一个节点的指针。通过这种方式,链表中的节点可以随意添加、删除、移动,使得链表非常灵活。

根据节点之间的连接方式,链表可以分为单向链表(每个节点只有一个指针指向下一个节点)和双向链表(每个节点有两个指针,分别指向前一个节点和后一个节点)。

链表的优点和缺点

链表相对于数组有以下几个优点:

  1. 动态性:链表的长度可以根据需要动态变化,而数组的长度是固定的。
  2. 插入和删除操作高效:链表在插入和删除元素时只需要改变指针的指向,时间复杂度是O(1);而数组在插入和删除元素时,需要移动其他元素,时间复杂度是O(n)。
  3. 内存效率高:链表可以根据需要动态分配内存,而数组需要一次性分配足够大的连续内存空间。

链表相对于数组也有一些缺点:

  1. 随机访问低效:链表中的元素并不是按照线性顺序存储的,要访问第N个元素需要从头节点开始依次向后查找,时间复杂度是O(n);而数组可以通过索引直接访问元素,时间复杂度是O(1)。
  2. 需要额外的内存空间:每个节点除了存储数据外,还需要存储指向下一个节点的指针,这会消耗额外的内存空间。

链表的实现

在Java中,可以使用类来实现链表。首先,我们需要定义一个表示节点的类:

class ListNode {
    int val;
    ListNode next;

    public ListNode(int val) {
        this.val = val;
        this.next = null;
    }
}

上面的代码定义了一个具有整数值和指向下一个节点的指针的节点类。每个节点都有一个构造函数用于初始化节点的值和指针。

接下来,我们可以定义一个链表类,用于操作链表:

class LinkedList {
    ListNode head;

    public LinkedList() {
        this.head = null;
    }

    public void add(int val) {
        ListNode newNode = new ListNode(val);
        if (head == null) {
            head = newNode;
        } else {
            ListNode temp = head;
            while (temp.next != null) {
                temp = temp.next;
            }
            temp.next = newNode;
        }
    }

    public void remove(int val) {
        ListNode prev = null;
        ListNode current = head;
        while (current != null) {
            if (current.val == val) {
                if (prev == null) {
                    head = current.next;
                } else {
                    prev.next = current.next;
                }
                break;
            }
            prev = current;
            current = current.next;
        }
    }

    public void print() {
        ListNode temp = head;
        while (temp != null) {
            System.out.print(temp.val + " ");
            temp = temp.next;
        }
        System.out.println();
    }
}

上面的代码定义了一个链表类,包含了添加节点、删除节点和打印链表的方法。其中,添加节点方法会将新节点添加到链表的末尾;删除节点方法会根据节点的值删除对应的节点;打印链表方法会按照顺序打印链表中的所有节点的值。

使用链表

使用链表时,我们需要创建一个链表对象,并调用相应的方法来操作链表。下面是一个使用链表的示例:

public class Main {
    public static void main(String[] args) {
        LinkedList list = new LinkedList();
        
        // 添加节点
        list.add(1);
        list.add(2);
        list.add(3);
        
        // 打印链表
        list.print(); //