C++入门-list

大家好啊,一周没见了。我们也闲话少说,直接发车,今天来聊聊C++中的list !
在这里插入图片描述

1. list的介绍

在C++标准库中,std::list是一个双向链表容器,它提供了高效的插入和删除操作,但访问元素的效率较低。std::list的特点包括:

  • 元素存储在链表中,插入和删除操作的时间复杂度为O(1);
  • 不支持随机访问,需要通过迭代器进行遍历;
  • 支持在任何位置插入和删除元素,不会造成内存的重新分配。

演示代码

下面是一个简单的示例代码,演示如何使用std::list

#include <iostream>
#include <list>

int main() {
    // 创建一个空的list
    std::list<int> mylist;

    // 在list末尾插入元素
    mylist.push_back(1);
    mylist.push_back(2);
    mylist.push_back(3);

    // 在list开头插入元素
    mylist.push_front(0);

    // 遍历list并输出元素
    for (auto it = mylist.begin(); it != mylist.end(); ++it) {
        std::cout << *it << " ";
    }

    return 0;
}

在上面的代码中,我们首先创建了一个空的std::list对象mylist,然后使用push_back在list的末尾插入了三个元素,使用push_front在list的开头插入了一个元素。最后,我们通过迭代器it遍历list,并输出元素的值。

std::list是一个非常灵活的容器,适合在需要频繁插入和删除操作的场景中使用。

1.2 list的使用

创建list并插入元素

#include <iostream>
#include <list>

int main() {
    // 创建一个空的list
    std::list<int> mylist;

    // 在list末尾插入元素
    mylist.push_back(1);
    mylist.push_back(2);
    mylist.push_back(3);

    // 在list开头插入元素
    mylist.push_front(0);

    // 遍历list并输出元素
    for (auto it = mylist.begin(); it != mylist.end(); ++it) {
        std::cout << *it << " ";
    }

    return 0;
}

在上面的示例中,我们创建了一个空的std::list对象mylist,然后使用push_back在list的末尾插入了三个元素,使用push_front在list的开头插入了一个元素。最后,通过迭代器遍历list并输出元素的值。

删除元素

#include <iostream>
#include <list>

int main() {
    std::list<int> mylist = {1, 2, 3, 4, 5};

    // 删除第一个元素
    mylist.pop_front();

    // 删除最后一个元素
    mylist.pop_back();

    // 删除指定位置的元素
    auto it = std::find(mylist.begin(), mylist.end(), 3);
    if (it != mylist.end()) {
        mylist.erase(it);
    }

    // 遍历list并输出元素
    for (auto num : mylist) {
        std::cout << num << " ";
    }

    return 0;
}

在上面的代码中,我们演示了如何使用pop_frontpop_back分别删除第一个元素和最后一个元素,以及如何使用erase删除指定位置的元素。

其他常用操作

除了插入和删除操作外,std::list还提供了许多其他常用操作,如size()获取元素个数、empty()判断是否为空、clear()清空所有元素等。

通过灵活运用这些操作,可以更好地利用std::list的特性,完成各种需求。

2.1 模拟实现list

在本节中,我们将尝试模拟实现一个简单的双向链表,类似于std::list的基本功能。我们将实现链表节点类和链表类,并添加常见的插入、删除、遍历等操作。

链表节点类的实现

首先,我们定义链表节点类Node,包含数据成员和指向前后节点的指针。

#include <iostream>

template <typename T>
struct Node {
    T data;
    Node* prev;
    Node* next;

    Node(const T& value) : data(value), prev(nullptr), next(nullptr) {}
};

链表类的实现

接下来,我们定义链表类MyList,包含头尾指针和链表大小,并实现插入、删除、遍历等操作。

template <typename T>
class MyList {
private:
    Node<T>* head;
    Node<T>* tail;
    size_t size;

public:
    MyList() : head(nullptr), tail(nullptr), size(0) {}

    void push_back(const T& value) {
        Node<T>* newNode = new Node<T>(value);
        if (head == nullptr) {
            head = tail = newNode;
        } else {
            tail->next = newNode;
            newNode->prev = tail;
            tail = newNode;
        }
        size++;
    }

    void pop_back() {
        if (size == 0) {
            return;
        }
        Node<T>* temp = tail;
        tail = tail->prev;
        delete temp;
        size--;
    }

    void print() {
        Node<T>* current = head;
        while (current != nullptr) {
            std::cout << current->data << " ";
            current = current->next;
        }
        std::cout << std::endl;
    }

    size_t getSize() const {
        return size;
    }

    ~MyList() {
        while (head != nullptr) {
            Node<T>* temp = head;
            head = head->next;
            delete temp;
        }
    }
};

演示代码

int main() {
    MyList<int> myList;

    myList.push_back(1);
    myList.push_back(2);
    myList.push_back(3);
    myList.print(); // 输出: 1 2 3

    myList.pop_back();
    myList.print(); // 输出: 1 2

    std::cout << "Size: " << myList.getSize() << std::endl; // 输出: Size: 2

    return 0;
}

在上面的示例中,我们模拟实现了一个简单的双向链表类MyList,包括了push_back插入元素、pop_back删除尾部元素、print打印链表内容、getSize获取链表大小等操作。

2.2 list的反向迭代器

在本节中,我们将讨论C++标准库中std::list提供的反向迭代器,以及如何使用它来逆向遍历链表中的元素。

反向迭代器的概念

std::list提供了rbegin()rend()成员函数,分别返回指向最后一个元素和指向第一个元素前一个位置的反向迭代器。通过反向迭代器,我们可以逆向遍历链表,实现从尾部到头部的遍历。

演示代码

下面是一个简单的示例代码,演示如何使用反向迭代器逆向遍历std::list

#include <iostream>
#include <list>

int main() {
    std::list<int> myList = {1, 2, 3, 4, 5};

    // 使用正向迭代器正向遍历
    std::cout << "正向遍历:" << std::endl;
    for (auto it = myList.begin(); it != myList.end(); ++it) {
        std::cout << *it << " ";
    }
    std::cout << std::endl;

    // 使用反向迭代器逆向遍历
    std::cout << "反向遍历:" << std::endl;
    for (auto rit = myList.rbegin(); rit != myList.rend(); ++rit) {
        std::cout << *rit << " ";
    }
    std::cout << std::endl;

    return 0;
}

在上面的示例中,我们首先创建了一个std::list并初始化了一些整数元素。然后,我们使用正向迭代器和反向迭代器分别进行正向和逆向遍历,并输出遍历结果。

详细解释

  • rbegin()返回指向最后一个元素的反向迭代器,rend()返回指向第一个元素前一个位置的反向迭代器。
  • 逆向遍历时,需要使用rbegin()作为起始迭代器,rend()作为结束迭代器,并通过++rit递增迭代器来遍历元素。

通过反向迭代器,我们可以方便地实现链表的逆向遍历操作,提高了代码的可读性和灵活性。

3. list与vector的对比

在本节中,我们将比较C++标准库中的std::liststd::vector两种容器,分析它们的特点、优缺点以及适用场景。

3.1 list与vector的特点

  • std::list

    • 底层实现为双向链表,支持高效的插入和删除操作。
    • 不支持随机访问,访问元素的时间复杂度为O(n)。
    • 适用于频繁的插入和删除操作,不需要随机访问元素的场景。
  • std::vector

    • 底层实现为动态数组,支持随机访问和快速的尾部插入删除操作。
    • 支持通过下标快速访问元素,访问时间复杂度为O(1)。
    • 适用于需要频繁访问元素、尾部插入删除操作和内存连续存储的场景。

3.2 比较示例

下面是一个简单的示例代码,演示了std::liststd::vector的对比:

#include <iostream>
#include <list>
#include <vector>

int main() {
    // 使用std::list
    std::list<int> myList;
    for (int i = 0; i < 5; ++i) {
        myList.push_back(i);
    }

    // 使用std::vector
    std::vector<int> myVector;
    for (int i = 0; i < 5; ++i) {
        myVector.push_back(i);
    }

    // 访问元素比较
    std::cout << "std::list元素访问:" << std::endl;
    for (auto it = myList.begin(); it != myList.end(); ++it) {
        std::cout << *it << " ";
    }
    std::cout << std::endl;

    std::cout << "std::vector元素访问:" << std::endl;
    for (int i = 0; i < myVector.size(); ++i) {
        std::cout << myVector[i] << " ";
    }
    std::cout << std::endl;

    return 0;
}

在上面的示例中,我们分别使用std::liststd::vector存储相同的元素,并比较它们的元素访问方式。

详细解释

  • std::list适用于频繁的插入删除操作,不支持随机访问,访问元素需要通过迭代器。
  • std::vector适用于需要随机访问、尾部插入删除操作的场景,可以通过下标直接访问元素。

根据具体的需求和场景选择合适的容器,可以提高代码的效率和性能。

4. 相关OJ题

在本节中,我们将通过一些相关的OJ题目来帮助大家更好地理解和运用C++中的std::list容器。

OJ题目1:反转链表

问题描述: 给定一个单向链表,将其反转并返回新的头节点。

示例输入:

1 -> 2 -> 3 -> 4 -> 5

示例输出:

5 -> 4 -> 3 -> 2 -> 1

解题思路: 使用std::list可以方便地实现链表的反转操作。

#include <iostream>
#include <list>

struct ListNode {
    int val;
    ListNode* next;
    ListNode(int x) : val(x), next(nullptr) {}
};

ListNode* reverseList(ListNode* head) {
    std::list<int> tempList;
    ListNode* curr = head;
    while (curr) {
        tempList.push_front(curr->val);
        curr = curr->next;
    }

    ListNode* newHead = new ListNode(0);
    ListNode* temp = newHead;
    for (int val : tempList) {
        temp->next = new ListNode(val);
        temp = temp->next;
    }

    return newHead->next;
}

int main() {
    ListNode* head = new ListNode(1);
    head->next = new ListNode(2);
    head->next->next = new ListNode(3);
    head->next->next->next = new ListNode(4);
    head->next->next->next->next = new ListNode(5);

    ListNode* reversedHead = reverseList(head);

    while (reversedHead) {
        std::cout << reversedHead->val << " ";
        reversedHead = reversedHead->next;
    }

    return 0;
}

在上面的示例中,我们通过std::list实现了链表的反转操作,将链表元素存储在std::list中,然后倒序构建新的链表。

OJ题目2:合并两个有序链表

问题描述: 给定两个有序单向链表,将它们合并为一个有序链表并返回。

示例输入:

List1: 1 -> 3 -> 5
List2: 2 -> 4 -> 6

示例输出:

1 -> 2 -> 3 -> 4 -> 5 -> 6

解题思路: 使用std::list的排序功能可以方便地合并两个有序链表。

#include <iostream>
#include <list>

struct ListNode {
    int val;
    ListNode* next;
    ListNode(int x) : val(x), next(nullptr) {}
};

ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
    std::list<int> tempList;
    while (l1) {
        tempList.push_back(l1->val);
        l1 = l1->next;
    }
    while (l2) {
        tempList.push_back(l2->val);
        l2 = l2->next;
    }

    tempList.sort();

    ListNode* newHead = new ListNode(0);
    ListNode* temp = newHead;
    for (int val : tempList) {
        temp->next = new ListNode(val);
        temp = temp->next;
    }

    return newHead->next;
}

int main() {
    ListNode* l1 = new ListNode(1);
    l1->next = new ListNode(3);
    l1->next->next = new ListNode(5);

    ListNode* l2 = new ListNode(2);
    l2->next = new ListNode(4);
    l2->next->next = new ListNode(6);

    ListNode* mergedList = mergeTwoLists(l1, l2);

    while (mergedList) {
        std::cout << mergedList->val << " ";
        mergedList = mergedList->next;
    }

    return 0;
}

在上面的示例中,我们通过std::list的排序功能实现了两个有序链表的合并操作,将两个链表元素存储在std::list中,然后进行排序构建新的有序链表。

好了,感谢大家看到这,如果觉得本篇文章对你有帮助的话,还请点个赞支持一下,有什么问题也可以评论区留言,那么我们下次再见了,Peace~
在这里插入图片描述

  • 24
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
目录 +-- 第一章 VC入门 |------ 1.1 如何学好VC |------ 1.2 理解Windows消息机制 |------ 1.3 利用Visual C++/MFC开发Windows程序的优势 |------ 1.4 利用MFC进行开发的通用方法介绍 |------ 1.5 MFC中常用类,宏,函数介绍 +-- 第二章 图形输出 |------ 2.1 和GUI有关的各种对象 |------ 2.2 在窗口中输出文字 |------ 2.3 使用点,刷子,笔进行绘图 |------ 2.4 在窗口中绘制设备相关位图,图标,设备无关位图 |------ 2.5 使用各种映射方式 |------ 2.6 多边形和剪贴区域 +-- 第三章 文档视结构 |------ 3.1 文档 视图 框架窗口间的关系和消息传送规律 |------ 3.2 接收用户输入 |------ 3.3 使用菜单 |------ 3.4 文档,视,框架之间相互作用 |------ 3.5 利用序列化进行文件读写 |------ 3.6 MFC中所提供的各种视类介绍 +-- 第四章 窗口控件 |------ 4.1 Button |------ 4.2 Static Box |------ 4.3 Edit Box |------ 4.4 Scroll Bar |------ 4.5 List Box/Check List Box |------ 4.6 Combo Box/Combo Box Ex |------ 4.7 Tree Ctrl |------ 4.8 List Ctrl |------ 4.9 Tab Ctrl |------ 4.A Tool Bar |------ 4.B Status Bar |------ 4.C Dialog Bar |------ 4.D 利用AppWizard创建并使用ToolBar StatusBar Dialog Bar |------ 4.E General Window |------ 4.F 关于WM_NOTIFY的使用方法 +-- 第五章 对话框 |------ 5.1 使用资源编辑器编辑对话框 |------ 5.2 创建有模式对话框 |------ 5.3 创建无模式对话框 |------ 5.4 在对话框中进行消息映射 |------ 5.5 在对话框中进行数据交换和数据检查 2 |------ 5.6 使用属性对话框 |------ 5.7 使用通用对话框 |------ 5.8 建立以对话框为基础的应用 |------ 5.9 使用对话框作为子窗口 +-- 第六章 网络通信开发 |------ 6.1 WinSock介绍 |------ 6.2 利用WinSock进行无连接的通信 +------ 6.3 利用WinSock建立有连接的通信
第一章 VC 入门 ............................................................................................................................... 2 1.1 如何学好 VC ..................................................................................................................... 2 1.2 理解 Windows 消息机制 .................................................................................................. 3 1.3 利用 Visual C++/MFC 开发 Windows 程序的优势 ........................................................ 5 1.4 利用 MFC 进行开发的通用方法介绍 ............................................................................. 6 1.5 MFC 中常用类,宏,函数介绍 ....................................................................................... 7 第二章 图形输出 ............................................................................................................................ 9 2.1 和 GUI 有关的各种对象................................................................................................... 9 2.2 在窗口中输出文字......................................................................................................... 11 2.3 使用点,刷子,笔进行绘图......................................................................................... 16 2.4 在窗口中绘制设备相关位图,图标,设备无关位图 ................................................. 18 2.5 使用各种映射方式......................................................................................................... 20 第三章 文档视结构 ...................................................................................................................... 23 3.1 文档 视图 框架窗口间的关系和消息传送规律 ......................................................... 23 3.2 接收用户输入................................................................................................................. 24 3.3 使用菜单 ........................................................................................................................ 27 3.4 文档,视,框架之间相互作用 ..................................................................................... 31 3.5 利用序列化进行文件读写............................................................................................. 32 3.6 MFC 中所提供的各种视类介绍 ..................................................................................... 35 第四章 窗口控件 .......................................................................................................................... 35 4.1 Button ............................................................................................................................ 35 4.2 Static Box .................................................................................................................... 37 4.3 Edit Box ........................................................................................................................ 38 4.4 Scroll Bar .................................................................................................................... 38 4.5 List Box/Check List Box .......................................................................................... 39 4.6 Combo Box ...................................................................................................................... 40 4.7 Tree Ctrl ........................................................................................................................... 42 4.8 List Ctrl ...................................................................................................................... 45 4.9 Tab Ctrl ........................................................................................................................ 48 4.A Tool Bar ........................................................................................................................ 49 4.B Status Bar .................................................................................................................... 50 4.C Dialog Bar .................................................................................................................... 51 4.D 利用 AppWizard 创建并使用 ToolBar StatusBar Dialog Bar ............................... 51 4.E General Window ............................................................................................................ 55 4.F 关于 WM_NOTIFY 的使用方法 .................................................................................. 57 第五章 对话框 .............................................................................................................................. 58 5.1 使用资源编辑器编辑对话框......................................................................................... 58 5.2 创建有模式对话框......................................................................................................... 59 5.3 创建无模式对话框 .......................................................................................................... 61 5.4 在对话框中进行消息映射............................................................................................. 65 5.5 在对话框中进行数据交换和数据检查 ......................................................................... 67 5.6 使用属性对话框............................................................................................................. 70 5.7 使用通用对话框............................................................................................................. 73 5.8 建立以对话框为基础的应用......................................................................................... 74 5.9 使用对话框作为子窗口................................................................................................. 75 第六章 网络通信开发 .................................................................................................................. 77 6.1 WinSock 介绍 ................................................................................................................. 77 6.2 利用 WinSock 进行无连接的通信................................................................................. 80 6.3 利用 WinSock 进行有连接的通信................................................................................. 82
STL是指标准模板库(Standard Template Library),它是C++语言的一部分,提供了一系列的模板类和函数,用于支持通用的数据结构和算法。STL的目标是提供高效、可重用和可扩展的组件,以便开发人员能够更轻松地编写高质量的代码。STL包含了许多常见的数据结构,如vector、list、set、map等,以及各种算法,比如排序、查找、遍历等。通过使用STL,开发人员可以更加高效地处理各种数据结构和算法的问题,提高代码的开发效率和质量。 在STL中,我们可以使用各种容器来存储和管理数据。例如,我们可以使用std::map来创建一个键值对的映射,其中每个键都有一个与之相关联的值。下面是一个示例代码,展示了如何创建和使用一个std::map对象: std::map<std::string, int> disMap() { std::map<std::string, int> tempMap{ {"C语言教程",10},{"STL教程",20} }; return tempMap; } std::map<std::string, int> newMap(disMap()); 在这个示例中,disMap()函数创建了一个临时的std::map对象,并初始化了其中的一些键值对。然后,使用移动构造函数将这个临时对象移动到了一个新的std::map对象newMap中。最终,我们可以通过newMap对象来访问和操作这些键值对。 综上所述,STL是C++中的标准模板库,提供了一系列的模板类和函数,用于支持通用的数据结构和算法。STL的使用可以提高代码的开发效率和质量,并且通过各种容器和算法,可以方便地处理各种数据结构和算法的问题。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [C++ STL详解超全总结(快速入门STL)](https://blog.csdn.net/qq_50285142/article/details/114026148)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* *3* [【C++实验】阅读STL源码并分析](https://blog.csdn.net/qq_35760825/article/details/125311509)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值