golang,go,博客,开源,编程

单向链表

Published on with 0 views and 0 comments

单向链表(Singly Linked List)是一种链式数据结构,其中的每个节点包含两个部分:数据和指向下一个节点的指针。单向链表中的每个节点只能向前指向下一个节点,无法向后访问,意味着只能从链表的头部开始遍历,直到最后一个节点。

单向链表的结构:

单向链表的节点通常包含以下两个部分:

  1. 数据域(data):存储节点的数据。
  2. 指向下一个节点的指针(next):指向链表中的下一个节点。

单向链表的操作:

  1. 插入操作
    • 在链表的头部插入节点。
    • 在链表的尾部插入节点。
    • 在链表的中间插入节点。
  2. 删除操作
    • 删除头节点。
    • 删除尾节点(需要遍历整个链表)。
    • 删除中间的某个节点。
  3. 查找操作
    • 查找指定数据的节点。

单向链表的优势:

  • 节省空间:每个节点只需要一个指针来指向下一个节点,内存消耗比双向链表少。
  • 结构简单:因为只需要一个指针来连接节点,代码实现相对简单。

单向链表的缺点:

  • 只能单向遍历:只能从头节点开始,向后遍历链表,无法进行反向遍历。
  • 删除操作较麻烦:如果想删除一个中间节点,需要访问该节点的前一个节点(通常从头节点开始遍历,找到该节点的前一个节点)。

单向链表的示意图:

  Head → Node1 → Node2 → Node3 → Null

在这个示意图中:

  • Head 是链表的头节点。
  • 每个节点只通过一个 next 指针指向下一个节点。
  • 最后一个节点的 next 指针为 Null,表示链表的结尾。

示例:单向链表节点结构(C++实现)

#include <iostream>
using namespace std;

// 单向链表节点
struct Node {
    int data;   // 节点数据
    Node* next; // 指向下一个节点
};

// 单向链表类
class SinglyLinkedList {
public:
    Node* head; // 链表头指针

    SinglyLinkedList() {
        head = nullptr;
    }

    // 在链表头部插入新节点
    void insertAtHead(int value) {
        Node* newNode = new Node();
        newNode->data = value;
        newNode->next = head; // 新节点指向当前的头节点
        head = newNode;       // 更新头指针
    }

    // 在链表尾部插入新节点
    void insertAtTail(int value) {
        Node* newNode = new Node();
        newNode->data = value;
        newNode->next = nullptr;

        if (head == nullptr) {
            head = newNode;  // 如果链表为空,新的节点成为头节点
        } else {
            Node* temp = head;
            while (temp->next != nullptr) {
                temp = temp->next;
            }
            temp->next = newNode; // 将新节点插入到链表的末尾
        }
    }

    // 打印链表
    void printList() {
        Node* temp = head;
        while (temp != nullptr) {
            cout << temp->data << " ";
            temp = temp->next;
        }
        cout << endl;
    }
  
    // 删除指定节点(通过值)
    void deleteNode(int value) {
        if (head == nullptr) return;  // 空链表

        if (head->data == value) {  // 如果是删除头节点
            Node* temp = head;
            head = head->next;  // 将头指针移到下一个节点
            delete temp;
            return;
        }

        Node* temp = head;
        while (temp->next != nullptr && temp->next->data != value) {
            temp = temp->next;
        }

        if (temp->next == nullptr) {
            cout << "Node not found!" << endl;
            return;
        }

        Node* nodeToDelete = temp->next;
        temp->next = temp->next->next;  // 删除节点
        delete nodeToDelete;
    }
};

int main() {
    SinglyLinkedList list;

    // 插入节点
    list.insertAtHead(10);
    list.insertAtHead(20);
    list.insertAtTail(30);

    // 打印链表
    cout << "Linked List: ";
    list.printList();  // 输出: 20 10 30

    // 删除节点
    list.deleteNode(10);
    cout << "Linked List after deletion: ";
    list.printList();  // 输出: 20 30

    return 0;
}

单向链表的时间复杂度:

  • 插入操作:O(1)(在头部插入时)。O(n)(在尾部插入时,因为需要遍历链表)。
  • 删除操作:O(1)(如果删除头节点)。O(n)(如果删除中间或尾部节点,因为需要遍历到目标节点的前一个节点)。
  • 查找操作:O(n)(需要线性扫描整个链表)。

总结:

单向链表是一种简单且高效的链式数据结构,适用于一些不需要频繁反向遍历的场景。它的优点是结构简单,内存消耗较少,缺点是只能单向遍历,并且删除操作相对较慢。如果你的应用场景中不需要复杂的反向操作或删除操作,单向链表是一个不错的选择。

如果你有任何具体问题或其他内容需要进一步探讨,随时告诉我!


标题:单向链表
作者:mooncakeee
地址:http://blog.dd95828.com/articles/2025/01/10/1736470914505.html
联系:scotttu@163.com