List链表-数据结构与算法链表结构

        链表是一种常见的线性数据结构,由节点组成,每个节点包含一个值和指向下一个节点的指针。链表可以动态地分配内存,不需要连续的存储空间。

        链表分为单向链表和双向链表。

自定义链表

链表结构定义

// 定义链表节点类
class Node {
public:
    int data;   // 节点值
    Node* next; // 指向下一个节点的指针

    Node(int value) {
        data = value;
        next = nullptr;
    }
};

        在双向链表中,还有一个 Node* pre成员变量;指向当前节点的前一个节点指针。

链表类的定义

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

public:
    LinkedList() {
        head = nullptr;
    }

    // 在链表末尾插入新节点
    void insert(int value) {
        Node* newNode = new Node(value);
        
        if (head == nullptr) {
            head = newNode;
        } else {
            Node* current = head;
            while (current->next != nullptr) {
                current = current->next;
            }
            current->next = newNode;
        }
        
        std::cout << "Inserted " << value << " into the list." << std::endl;
    }

    // 打印链表元素
    void display() {
        if (head == nullptr) {
            std::cout << "List is empty." << std::endl;
            return;
        }

        Node* current = head;

        while (current != nullptr) {
            std::cout << current->data << " ";
            current = current->next;
        }

        std::cout << std::endl;
    }
};

链表的使用

int main() {
    LinkedList list;

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

    // 打印链表元素
    std::cout << "Linked List: ";
    list.display();

    return 0;
}

标准库STL中链表

        在C++的STL(标准模板库)中,提供了std::list容器来实现链表。std::list是一个双向链表,它允许在常数时间内插入、删除和访问元素。

std::list用法举例

        使用std::list需要包含头文件 <list>

#include <iostream>
#include <list>

int main() {
    std::list<int> myList;

    // 在链表末尾插入元素
    myList.push_back(10);
    myList.push_back(20);
    myList.push_back(30);

    // 在链表开头插入元素
    myList.push_front(5);

    // 使用迭代器遍历并打印链表元素
    std::cout << "Linked List: ";
    for (auto it = myList.begin(); it != myList.end(); ++it) {
        std::cout << *it << " ";
    }
    
    return 0;
}

打印结果:Linked List: 5 10 20 30

list接口介绍

  1. 构造函数和析构函数:

    • list(): 默认构造函数,创建一个空链表。
    • list(size_type count, const T& value): 创建包含指定数量元素的链表,并将每个元素初始化为给定值。
    • list(const list& other): 复制构造函数,创建一个与另一个链表相同的副本。
    • ~list(): 析构函数,销毁链表并释放内存。
  2. 迭代器相关操作:

    • begin()end(): 返回指向第一个元素和尾后(最后一个元素之后)位置的迭代器。
    • rbegin()rend(): 返回指向最后一个元素和首前(第一个元素之前)位置的逆向迭代器。
  3. 容量查询操作:

    • empty(): 判断链表是否为空。
    • size(): 返回链表中元素的数量。
  4. 元素访问操作:

    • front(): 返回链表中第一个元素的引用。
    • back(): 返回链表中最后一个元素的引用。
  5. 修改容器内容操作:

    • push_back(const T& value): 在链表末尾插入一个元素。
    • pop_back(): 删除链表末尾的元素。
    • push_front(const T& value): 在链表开头插入一个元素。
    • pop_front(): 删除链表开头的元素。
    • insert(iterator pos, const T& value): 在指定位置之前插入一个元素。
    • erase(iterator pos): 删除指定位置处的元素。
    • clear(): 清空链表,删除所有元素。

list的一些操作

        1.遍历list内的元素

        2.逆序遍历list的元素

        3.反转list的元素

        4.查找list中是否有环

        5.条件插入,在指定位置插入元素

        6.查找元素,删除查找到的元素

        7.修改元素

list的应用场景,优缺点

std::list在以下场景中比较适合使用:

  1. 需要频繁在任意位置插入和删除元素:由于std::list是双向链表,插入和删除操作的时间复杂度为O(1),不需要移动其他元素。
  2. 需要在容器中进行大量的元素交换或移动:由于链表节点之间只需要改变指针,而不需要真正地移动元素本身,因此对于大量的元素交换或移动操作,std::list更高效。
    1. 不要求随机访问元素:由于链表是非连续存储结构,无法通过索引直接访问元素。如果需要经常随机访问元素,则使用std::vector可能更合适。        

优点:

  • 插入和删除操作高效:在任意位置插入或删除一个元素的时间复杂度为O(1)。
  • 支持快速的元素交换和移动操作:只需修改节点指针,不需要实际移动元素本身。
  • 动态内存管理:可以根据需要自动分配和释放内存。

缺点:

  • 访问某个特定位置上的元素效率较低:由于链表是非连续存储结构,无法通过索引直接访问到指定位置上的元素,必须从头遍历到目标位置。
  • 占用额外的存储空间:除了存储元素本身外,还需要额外的指针来连接节点,会占用更多内存。
  • 不支持随机访问:无法像数组一样通过索引直接访问元素,只能通过遍历链表来查找特定元素。

        综上,std::list适合在需要频繁进行插入和删除操作、不要求随机访问元素的场景中使用。如果需要经常随机访问元素,使用其他容器如std::vectorstd::deque

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值