• 双向链表std::list和单向链表std::forward_list


    中文标准库:std::list

    中文标准库:std::forward_list

    一、简介

    • list是由双向链表实现的,内存空间是不连续的。由链表的实现原理可知:

    优点:插入和删除非常快。只需要在插入的地方更改指针的指向即可,不用移动数据。

    缺点:不支持随机访问,查询效率较低,时间复杂度为O(n)

    • forward_list是一个单向链表,只支持单向顺序访问,在链表的任何位置进行插入/删除操作都非常快。

    list的迭代器不支持+、-操作,支持++、--操作(vector迭代器支持+、-、++、--等操作),可以使用std::advance达到+的目的

    二、构造

    初始化列表:initializer_list

    // C++11 初始化列表语法:
    std::list<std::string> words1{ "the", "frogurt", "is", "also", "cursed" };
    
    // words2 == words1
    std::list<std::string> words2(words1.begin(), words1.end());
    
    // words3 == words1
    std::list<std::string> words3(words1);
    
    // words4 为 {"Mo", "Mo", "Mo", "Mo", "Mo"}
    std::list<std::string> words4(5, "Mo");
    

    三、增加元素

    右值引用

    • insert、emplace:在某一给定位置插入元素
    template <class... Args>
      iterator emplace (const_iterator position, Args&&... args);
    
    //single element(1)
    iterator insert(const_iterator position, const value_type& val);
    //fill(2)
    iterator insert(const_iterator position, size_type n, const value_type& val);
    //range(3)
    template <class InputIterator>
    iterator insert(const_iterator position, InputIterator first, InputIterator last);
    //move(4)
    iterator insert(const_iterator position, value_type&& val);
    //initializer list(5)
    iterator insert(const_iterator position, initializer_list<value_type> il);
    
    • emplace_back、push_back:在容器尾部插入元素
    template <class... Args>
      void emplace_back (Args&&... args);
    
    void push_back (const value_type& val);
    void push_back (value_type&& val);
    
    • emplace_front、push_front:在容器头部插入元素
    template <class... Args>
      void emplace_front (Args&&... args);
    
    void push_front (const value_type& val);
    void push_front (value_type&& val);
    
    • 示例代码:
    std::list<int> List1;
    List1.insert(List1.begin(), { 1,2 });     //1,2
    List1.emplace(List1.end(), std::move(3)); //1,2,3
    List1.emplace_back(4);                    //1,2,3,4
    List1.emplace_front(5);                   //5,1,2,3,4
    List1.push_back(6);			  //5,1,2,3,4,6
    List1.push_front(7);			  //7,5,1,2,3,4,6
    

    四、删除元素

    • clear:清空元素

    void clear() noexcept;

    • pop_back、pop_front:移除尾部或首部元素

    如果容器为空,这两个函数会中断(不是抛出异常)

    void pop_back();
    void pop_front();
    
    • erase:删除指定位置的元素
    iterator erase (const_iterator position);  //仅仅删除这个位置的一个元素
    iterator erase (const_iterator first, const_iterator last);  //删除first到last的所有元素
    
    • remove:删除指定元素

    void remove (const value_type& val);

    • remove_if、erase_if(C++20):擦除所有满足特定判别标准的元素

    注意:删除的是pred返回true的元素。

    template< class T, class Alloc, class Pred >
    typename std::list<T, Alloc>::size_type erase_if(std::list<T, Alloc>& c, Pred pred);
    
    template <class Predicate>
      void remove_if (Predicate pred);
    

    lambda表达式

    • 示例代码:
    std::list<int> List2{ 0,1,2,3,4,5,6,7,8 };
    List2.pop_back();  //0,1,2,3,4,5,6,7
    List2.pop_front(); //1,2,3,4,5,6,7
    List2.erase(List2.begin());  //2,3,4,5,6,7
    List2.erase(std::find(List2.begin(), List2.end(), 5), List2.end());  //2,3,4
    List2.remove(2); //3,4
    List2.remove_if([](int n) {return n == 4; }); //3
    List2.clear();  //清空
    

    五、修改元素

    • 修改

    list不能像vector一样通过[]修改元素,不过可以先删除需要修改的元素,再添加一个新的元素。

    • swap:交换
      注意:交换的两个list类型必须相同
      void swap (list& x);
    • 示例代码:
    std::list<int> List4{ 2,3,4 };
    std::list<int> List5{ 7,8,9 };
    List4.swap(List5);
    
    std::list<int> List6{ 1,2,3,4,5,6 };
    List5.remove(3);
    List6.emplace_back(7);
    
    • assign:替换原有的list的内容
      和swap相比,assign功能更强大,assign的参数可以是其他容器,也可以选择将list用容器中的一部分元素替换。
      list.assign(vector.begin(),vector.end());

    六、访问元素、查找元素

    注意:list没有自己的查找函数,如果要使用查找,可以用算法库(algorithm)中的std::find函数

    • front:访问第一个元素

    • back:访问最后一个元素

    • 示例代码:

    std::list<int> List3{ 1,2,3,4,5 };
    int front = List3.front();  //1
    int back = List3.back();    //5
    std::list<int>::iterator it = std::find(List3.begin(), List3.end(), 2);
    

    七、其他

    • 排序:sort()

    默认升序排序,若要使用降序排序:

    升序:sort(std::less<data-type>())

    降序:sort(std::greater<data-type>())

            List7.sort(std::greater<int>());  //降序
            List7.sort(std::less<int>());     //升序
    
    • 逆序:reverse()

    • 移除重复元素:unique()
      注意:不相邻的重复元素不会被删除

    • 合并:merge
      前提:两个已排序的list,且必须按升序排序(list::sort()默认升序排序)

    注意:归并完之后,x会被清空(即全部移动到调用对象中去)
    函数原型:

    void merge(list& x);
    void merge(list&& x);
    template <class Compare>
    void merge(list& x, Compare comp);
    template <class Compare>
    void merge(list&& x, Compare comp);
    

    示例代码:

    std::list<int> List7{ 8,7,7,9 };
    List7.sort();
    std::list<int> List8{ 5,3,3,2 };
    List8.sort();
    List7.merge(List8);
    
    • 转移元素:splice()

    函数原型:

    //entire list(1)
    void splice(const_iterator position, list& x);
    void splice(const_iterator position, list&& x);
    //single element(2)
    void splice(const_iterator position, list& x, const_iterator i);
    void splice(const_iterator position, list&& x, const_iterator i);
    //element range(3)
    void splice(const_iterator position, list& x, const_iterator first, const_iterator last);
    void splice(const_iterator position, list&& x, const_iterator first, const_iterator last);
    

    示例代码:

    std::list<int> List9{ 1,2,3,4,5 };
    std::list<int> List10{ 7,8,9 };
    auto it9 = List9.begin();
    std::advance(it9, 2); //迭代器指向的元素向后移动两位,指向3
    List9.splice(it9, List10);  //List9:1,2,7,8,9,3,4,5;List10为空
    
    std::list<int> List11{ 1,2,3 };
    std::list<int> List12{ 5,6,7,8,9 };
    auto it12 = List12.begin();
    std::advance(it12, 2);
    List11.splice(List11.begin(), List12, it12, List12.end());  //List11:7,8,9,1,2,3;Lis12:5,6
    

    完整代码

    点击查看代码
    #include <iostream>
    #include <algorithm>
    #include <list>
    
    int main()
    {
    	//插入
    	std::list<int> List1;
    	List1.insert(List1.begin(), { 1,2 });     //1,2
    	List1.emplace(List1.end(), std::move(3)); //1,2,3
    	List1.emplace_back(4);                    //1,2,3,4
    	List1.emplace_front(5);                   //5,1,2,3,4
    	List1.push_back(6);						  //5,1,2,3,4,6
    	List1.push_front(7);					  //7,5,1,2,3,4,6
    
    	//删除
    	std::list<int> List2{ 0,1,2,3,4,5,6,7,8 };
    	List2.pop_back();  //0,1,2,3,4,5,6,7
    	List2.pop_front(); //1,2,3,4,5,6,7
    	List2.erase(List2.begin());  //2,3,4,5,6,7
    	List2.erase(std::find(List2.begin(), List2.end(), 5), List2.end());  //2,3,4
    	List2.remove(2); //3,4
    	List2.remove_if([](int n) {return n == 4; }); //3
    	List2.clear();  //清空
    
    	//查找
    	std::list<int> List3{ 1,2,3,4,5 };
    	int front = List3.front();  //1
    	int back = List3.back();    //5
    	std::list<int>::iterator it = std::find(List3.begin(), List3.end(), 2);
    
    	//修改
    	std::list<int> List4{ 2,3,4 };
    	std::list<int> List5{ 7,8,9 };
    	List4.swap(List5);
    
    	std::list<int> List6{ 1,2,3,4,5,6 };
    	List5.remove(3);
    	List6.emplace_back(7);
    
    	//归并
    	std::list<int> List7{ 8,7,7,9 };
    	List7.sort();
    	std::list<int> List8{ 5,3,3,2 };
    	List8.sort();
    	List7.merge(List8);
    
    	//排序
    	List7.sort(std::greater<int>());  //降序
    	List7.sort(std::less<int>());     //升序
    
    	//移除相邻重复元素
    	List7.unique();
    
    	//逆序
    	List7.reverse();
    
    	//转移元素
    	std::list<int> List9{ 1,2,3,4,5 };
    	std::list<int> List10{ 7,8,9 };
    	auto it9 = List9.begin();
    	std::advance(it9, 2); //迭代器指向的元素向后移动两位,指向3
    	List9.splice(it9, List10);  //List9:1,2,7,8,9,3,4,5;List10为空
    
    	std::list<int> List11{ 1,2,3 };
    	std::list<int> List12{ 5,6,7,8,9 };
    	auto it12 = List12.begin();
    	std::advance(it12, 2);
    	List11.splice(List11.begin(), List12, it12, List12.end());  //List11:7,8,9,1,2,3;Lis12:5,6
    
    	return 0;
    }
    
  • 相关阅读:
    负载(Load)分析及问题排查
    MySQL 数据库规范--调优篇(终结篇)
    AbstractQueuedSynchronizer
    为什么String被设计为不可变?是否真的不可变?
    数据库 分库 分表 分区
    Oracle 数据库知识汇总篇
    小知识:如何判断数据文件的高水位线
    RHEL7安装11204 RAC的注意事项
    案例:DG主库未设置force logging导致备库坏块
    Oracle 11g RAC之HAIP相关问题总结
  • 原文地址:https://www.cnblogs.com/mmmmmmmmm/p/14812567.html
Copyright © 2020-2023  润新知