C++数据结构之链表

1.介绍

        链表是C++中常用的一种动态数据结构,它有一系列节点组成,每个节点包含数据和指向下一个节点的指针。链表与数组不同,它的内存分配是动态的,不需要连续的内存空间。

2.链表的基本概念

(1)节点(Node):每个节点包含两部分:

                数据域:存储数据

                指针域:指向下一个节点的地址。

        在C++中,节点通常用结构体或类表示。

(2)链表的类型:

                单向链表:每个节点只有一个指针,指向下一个节点。

                双向链表:每个节点有两个指针,分别指向前一个节点和后一个节点。

                循环链表:尾节点的指针指向头节点,形成一个环。

(3)链表的优点

                动态分配内存,不需要预先知道数据的大小。

                插入和删除操作效率高(时间复杂度为O(1),前提是已知插入/删除位置)。

(4)链表的缺点:

                访问元素需要从头节点开始遍历,时间复杂度为O(n)。

                需要额外的内存空间存储指针。

3.链表的具体实现

        (1)单向链表的实现以及各种操作。

#include <iostream>

// 定义链表节点
struct Node {
    int data;       // 数据域
    Node* next;     // 指针域,指向下一个节点

    // 构造函数
    Node(int val) : data(val), next(nullptr) {}
};

// 定义链表类
class LinkedList {
private:
    Node* head; // 头节点指针

public:
    // 构造函数
    LinkedList() : head(nullptr) {}

    // 析构函数,释放链表内存
    ~LinkedList() {
        Node* current = head;
        while (current != nullptr) {
            Node* next = current->next;
            delete current;
            current = next;
        }
    }

    // 在链表头部插入节点
    void insertAtHead(int val) {
        Node* newNode = new Node(val);
        newNode->next = head;
        head = newNode;
    }

    // 在链表尾部插入节点
    void insertAtTail(int val) {
        Node* newNode = new Node(val);
        if (head == nullptr) {
            head = newNode;
            return;
        }
        Node* current = head;
        while (current->next != nullptr) {
            current = current->next;
        }
        current->next = newNode;
    }

    // 删除链表中指定值的节点
    void deleteNode(int val) {
        if (head == nullptr) return;

        // 如果要删除的是头节点
        if (head->data == val) {
            Node* temp = head;
            head = head->next;
            delete temp;
            return;
        }

        // 查找要删除的节点
        Node* current = head;
        while (current->next != nullptr && current->next->data != val) {
            current = current->next;
        }

        // 如果找到要删除的节点
        if (current->next != nullptr) {
            Node* temp = current->next;
            current->next = current->next->next;
            delete temp;
        }
    }

    // 打印链表
    void printList() const {
        Node* current = head;
        while (current != nullptr) {
            std::cout << current->data << " -> ";
            current = current->next;
        }
        std::cout << "nullptr" << std::endl;
    }
};

        (2)双向链表的实现

        双向链表每个节点有两个指针,分别是前指针与后指针。

#include <iostream>

// 定义双向链表节点
struct Node {
    int data;
    Node* prev;
    Node* next;

    // 构造函数
    Node(int val) : data(val), prev(nullptr), next(nullptr) {}
};

// 定义双向链表类
class DoublyLinkedList {
private:
    Node* head; // 头节点指针

public:
    // 构造函数
    DoublyLinkedList() : head(nullptr) {}

    // 析构函数,释放链表内存
    ~DoublyLinkedList() {
        Node* current = head;
        while (current != nullptr) {
            Node* next = current->next;
            delete current;
            current = next;
        }
    }

    // 在链表尾部插入节点
    void insertAtTail(int val) {
        Node* newNode = new Node(val);
        if (head == nullptr) {
            head = newNode;
            return;
        }
        Node* current = head;
        while (current->next != nullptr) {
            current = current->next;
        }
        current->next = newNode;
        newNode->prev = current;
    }

    // 打印链表
    void printList() const {
        Node* current = head;
        while (current != nullptr) {
            std::cout << current->data << " <-> ";
            current = current->next;
        }
        std::cout << "nullptr" << std::endl;
    }
};
4.链表的应用场景

        动态数据存储:当数据量不确定时,链表可以动态分配内存。

        频繁插入和删除:链表在已知位置插入和删除效率高。

        实现其他数据结构:如栈、队列、哈希表等。

5.总结

        链表是一种灵活的数据结构,适合动态数据存储和频繁插入/删除的操作。

        单向链表简单易于实现,双向链表支持双向遍历。

        链表的缺点是访问元素效率较低,需要额外的内存存储指针。

        通过链表,可以更好地理解指针和动态内存管理的概念。

如有错误,敬请指正!!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值