单向链表:数据世界的 “单向小火车”

148 阅读4分钟

嘿,编程小白们!今天咱们要聊的这个东西,就像数据世界里的 “单向小火车”,它叫单向链表。听名字是不是感觉有点高大上?别担心,看完这篇文章,保准你能轻松拿捏它!

image.png

单向链表是什么?

想象一下,学校组织春游,同学们排着长长的队伍,每个人都只能看到前面同学的后脑勺,要是想知道队伍后面发生了什么,只能一个接一个传话。单向链表就和这个队伍差不多,它是一种数据结构,把数据一个接一个串起来,每个数据元素都住在一个叫节点的 “小房子” 里 。

每个节点 “小房子” 有两个 “小房间”:一个用来存放数据,另一个用来存放下一个节点的 “地址”(在 Java 里是引用)。这就像每个同学手里都拿着下一个同学的联系方式,通过这个联系方式,就能按顺序找到队伍里的所有人。不过,和双向链表不同的是,单向链表的节点只能 “看到” 后面的节点,看不到前面的。

用 Java 代码定义一个单向链表的节点,长这样:

class Node {
    int data;
    Node next;
    Node(int data) {
        this.data = data;
        this.next = null;
    }
}

在这段代码里,data 是存放数据的 “房间”,比如可以存数字、文字等信息;next 就是存放下一个节点 “地址” 的 “房间”。构造函数 Node(int data) 就像给每个节点 “小房子” 分配数据,同时先把 next 设为空,因为一开始还没连接其他节点呢。

单向链表的基本操作

1. 创建单向链表

创建单向链表就像召集同学们排队,我们先创建几个节点,再让它们按顺序 “手拉手” 连接起来。

class SinglyLinkedList {
    Node head;
    // 创建单向链表
    void createList() {
        Node node1 = new Node(1);
        Node node2 = new Node(2);
        Node node3 = new Node(3);
        node1.next = node2;
        node2.next = node3;
        head = node1;
    }
}

在 createList 方法中,我们先创建了三个节点,分别存着数字 1、2、3。然后让 node1 的 next 指向 node2,node2 的 next 指向 node3,这样节点就按顺序连接起来了。最后把 head 设为 node1,head 就像是队伍的 “排头兵”,通过它就能找到整个链表的所有节点。

2. 插入节点

插入节点就好比中途有新同学加入队伍,插入的位置不同,操作也不一样,我们以在链表头部插入为例。

    // 在头部插入节点
    void insertAtHead(int data) {
        Node newNode = new Node(data);
        newNode.next = head;
        head = newNode;
    }

先创建一个新节点 newNode 存放要插入的数据。然后让新节点的 next 指向原来的头节点 head,这就相当于新同学拉住了原来排头兵的手。最后把 head 更新为新节点,这样新节点就成了新的 “排头兵”,成功加入队伍最前面啦!

3. 删除节点

删除节点就像有同学中途有事离开队伍,我们以删除指定数据的节点为例。

    // 删除指定数据的节点
    void deleteNode(int data) {
        Node current = head;
        Node prev = null;
        while (current != null && current.data != data) {
            prev = current;
            current = current.next;
        }
        if (current == null) {
            return;
        }
        if (prev == null) {
            head = current.next;
        } else {
            prev.next = current.next;
        }
    }

从链表头节点 head 开始,用 current 节点一个个查看数据,prev 节点用来记住 current 的前一个节点。当找到要删除数据的节点时,如果这个节点是头节点(prev == null),就把 head 更新为它后面的节点;如果不是头节点,就让它前一个节点的 next 直接跳过它,指向它后面的节点,这样就把这个节点从链表中 “移除” 啦!

4. 遍历单向链表

遍历单向链表就像老师挨个点名,从队伍第一个同学开始,一个个往后叫。

    // 遍历单向链表
    void traverse() {
        Node current = head;
        while (current != null) {
            System.out.print(current.data + " ");
            current = current.next;
        }
    }

从链表头节点 head 出发,只要当前节点 current 不是空的,就打印出它存的数据,然后让 current 指向下一个节点,直到把整个链表的节点都 “访问” 一遍,这样就完成了遍历操作。

单向链表的优缺点

单向链表虽然方便,但也不是十全十美,它有自己的 “小脾气”:

  • 优点:结构简单,实现起来容易;在插入和删除节点时,不需要像双向链表那样处理前后两个方向的引用,操作相对轻松。
  • 缺点:只能单向遍历,要是想从后面往前找数据,那就只能老老实实从头开始;而且如果要删除中间某个节点,需要先找到它前面的节点,灵活性不如双向链表。

现在,你是不是对单向链表这个 “单向小火车” 了如指掌啦?以后在编程的世界里,遇到需要按顺序存储和处理数据,又不需要频繁反向查找的场景,就可以放心让单向链表 “上场” 啦!快动手敲敲代码,亲自体验一下单向链表的魅力吧!