• list链表


    1. list基本概念

    功能:将数据进行链式存储

    链表(list)是一种物理存储单元上非连续的存储结构,数据元素的逻辑顺序是通过链表中的指针链接实现的

    链表的组成:链表由一系列结点组成

    结点的组成:一个是存储数据元素的数据域,另一个是存储下一个结点地址的指针域

    STL中的链表是一个双向循环链表

    由于链表的存储方式并不是连续的内存空间,因此链表list中的迭代器只支持前移和后移,属于双向迭代器

    1.1 list的优点:

    采用动态存储分配,不会造成内存浪费和溢出

    链表执行插入和删除操作十分方便,修改指针即可,不需要移动大量元素

    1.2 list的缺点:

    链表灵活,但是空间(指针域) 和 时间(遍历)额外耗费较大

    List有一个重要的性质,插入操作和删除操作都不会造成原有list迭代器的失效,这在vector是不成立的。

    总结:STL中List和vector是两个最常被使用的容器,各有优缺点

    2. list构造函数

    功能描述:

    创建list容器

    函数原型:

    1. list lst; //list采用采用模板类实现,对象的默认构造形式:
    2. list(beg,end); //构造函数将[beg, end)区间中的元素拷贝给本身。
    3. list(n,elem); //构造函数将n个elem拷贝给本身。
    4. list(const list &lst); //拷贝构造函数。

    总结:list构造方式同其他几个STL常用容器,熟练掌握即可

    示例:

    list_main1.cpp

    1. #include
    2. using namespace std;
    3. #include
    4. //list容器构造函数
    5. void printList( const list<int>&L)
    6. {
    7. for (list<int>::const_iterator it = L.begin(); it != L.end(); it++)
    8. {
    9. cout << *it << " ";
    10. }
    11. cout << endl;
    12. }
    13. void test01()
    14. {
    15. //创建list容器
    16. list<int>L1; //默认构造
    17. //添加数据
    18. L1.push_back(10);
    19. L1.push_back(20);
    20. L1.push_back(30);
    21. L1.push_back(40);
    22. //遍历容器
    23. printList(L1);
    24. //区间方式构造
    25. list<int>L2(L1.begin(), L1.end());
    26. printList(L2);
    27. //拷贝构造
    28. list<int>L3(L2);
    29. printList(L3);
    30. //n个elem
    31. list<int>L4(10, 1000);
    32. printList(L4);
    33. }
    34. int main() {
    35. test01();
    36. system("pause");
    37. return 0;
    38. }

    3. list 赋值和交换

    功能描述:

    给list容器进行赋值,以及交换list容器

    函数原型:

    1. assign(beg, end); //将[beg, end)区间中的数据拷贝赋值给本身。
    2. assign(n, elem); //将n个elem拷贝赋值给本身。
    3. list& operator=(const list &lst); //重载等号操作符
    4. swap(lst); //将lst与本身的元素互换。

    总结:list赋值和交换操作能够灵活运用即可

    示例:

    list_main2.cpp

    1. #include
    2. using namespace std;
    3. #include
    4. //list容器赋值和交换
    5. void printList(const list<int>&L)
    6. {
    7. for (list<int>::const_iterator it = L.begin(); it != L.end(); it++)
    8. {
    9. cout << *it << " ";
    10. }
    11. cout << endl;
    12. }
    13. //赋值
    14. void test01()
    15. {
    16. list<int>L1;
    17. L1.push_back(10);
    18. L1.push_back(20);
    19. L1.push_back(30);
    20. L1.push_back(40);
    21. printList(L1);
    22. list<int>L2;
    23. L2 = L1; // operator= 赋值
    24. printList(L2);
    25. list<int>L3;
    26. L3.assign(L2.begin(), L2.end());
    27. printList(L3);
    28. list<int>L4;
    29. L4.assign(10, 100);
    30. printList(L4);
    31. }
    32. //交换
    33. void test02()
    34. {
    35. list<int>L1;
    36. L1.push_back(10);
    37. L1.push_back(20);
    38. L1.push_back(30);
    39. L1.push_back(40);
    40. list<int>L2;
    41. L2.assign(10, 100);
    42. cout << "交换前: " << endl;
    43. printList(L1);
    44. printList(L2);
    45. L1.swap(L2);
    46. cout << "交换后: " << endl;
    47. printList(L1);
    48. printList(L2);
    49. }
    50. int main() {
    51. //test01();
    52. test02();
    53. system("pause");
    54. return 0;
    55. }

    4. list 大小操作

    功能描述:

    对list容器的大小进行操作

    函数原型:

    1. size(); //返回容器中元素的个数
    2. empty(); //判断容器是否为空
    3. resize(num); //重新指定容器的长度为num,若容器变长,则以默认值填充新位置。
    4. //如果容器变短,则末尾超出容器长度的元素被删除。
    5. resize(num, elem); //重新指定容器的长度为num,若容器变长,则以elem值填充新位置。
    6. //如果容器变短,则末尾超出容器长度的元素被删除。

    总结:

    判断是否为空 --- empty

    返回元素个数 --- size

    重新指定个数 --- resize

    示例

    list_main3.cpp

    1. #include
    2. using namespace std;
    3. #include
    4. //list容器大小操作
    5. void printList(const list<int>&L)
    6. {
    7. for (list<int>::const_iterator it = L.begin(); it != L.end(); it++)
    8. {
    9. cout << *it << " ";
    10. }
    11. cout << endl;
    12. }
    13. void test01()
    14. {
    15. list<int>L1;
    16. L1.push_back(10);
    17. L1.push_back(20);
    18. L1.push_back(30);
    19. L1.push_back(40);
    20. printList(L1);
    21. //判断容器是否为空
    22. if (L1.empty())
    23. {
    24. cout << "L1为空" << endl;
    25. }
    26. else
    27. {
    28. cout << "L1不为空" << endl;
    29. cout << "L1的元素个数为: " << L1.size() << endl;
    30. }
    31. //重新指定大小
    32. L1.resize(10, 10000);
    33. printList(L1);
    34. L1.resize(2);
    35. printList(L1);
    36. }
    37. int main() {
    38. test01();
    39. system("pause");
    40. return 0;
    41. }

    5. list 插入和删除

    功能描述:

    对list容器进行数据的插入和删除

    函数原型:

    1. push_back(elem);//在容器尾部加入一个元素
    2. pop_back();//删除容器中最后一个元素
    3. push_front(elem);//在容器开头插入一个元素
    4. pop_front();//从容器开头移除第一个元素
    5. insert(pos,elem);//在pos位置插elem元素的拷贝,返回新数据的位置。
    6. insert(pos,n,elem);//在pos位置插入n个elem数据,无返回值。
    7. insert(pos,beg,end);//在pos位置插入[beg,end)区间的数据,无返回值。
    8. clear();//移除容器的所有数据
    9. erase(beg,end);//删除[beg,end)区间的数据,返回下一个数据的位置。
    10. erase(pos);//删除pos位置的数据,返回下一个数据的位置。
    11. remove(elem);//删除容器中所有与elem值匹配的元素。

    总结:

    尾插 --- push_back

    尾删 --- pop_back

    头插 --- push_front

    头删 --- pop_front

    插入 --- insert

    删除 --- erase

    移除 --- remove

    清空 --- clear

    示例

    list_main4.cpp

    1. #include
    2. using namespace std;
    3. #include
    4. //list容器插入和删除
    5. /*
    6. - push_back(elem);//在容器尾部加入一个元素
    7. - pop_back();//删除容器中最后一个元素
    8. - push_front(elem);//在容器开头插入一个元素
    9. - pop_front();//从容器开头移除第一个元素
    10. - insert(pos,elem);//在pos位置插elem元素的拷贝,返回新数据的位置。
    11. - insert(pos,n,elem);//在pos位置插入n个elem数据,无返回值。
    12. - insert(pos,beg,end);//在pos位置插入[beg,end)区间的数据,无返回值。
    13. - clear();//移除容器的所有数据
    14. - erase(beg,end);//删除[beg,end)区间的数据,返回下一个数据的位置。
    15. - erase(pos);//删除pos位置的数据,返回下一个数据的位置。
    16. - remove(elem);//删除容器中所有与elem值匹配的元素。
    17. */
    18. void printList( const list<int>&L)
    19. {
    20. for (list<int>::const_iterator it = L.begin(); it != L.end(); it++)
    21. {
    22. cout << *it << " ";
    23. }
    24. cout << endl;
    25. }
    26. void test01()
    27. {
    28. list<int>L;
    29. //尾插
    30. L.push_back(10);
    31. L.push_back(20);
    32. L.push_back(30);
    33. //头插
    34. L.push_front(100);
    35. L.push_front(200);
    36. L.push_front(300);
    37. // 300 200 100 10 20 30
    38. printList(L);
    39. //尾删
    40. L.pop_back();
    41. // 300 200 100 10 20
    42. printList(L);
    43. //头删
    44. L.pop_front();
    45. // 200 100 10 20
    46. printList(L);
    47. //insert插入
    48. list<int>::iterator it = L.begin();
    49. L.insert(++it, 1000);
    50. // 200 1000 100 10 20
    51. printList(L);
    52. //删除
    53. it = L.begin();
    54. L.erase(++it);
    55. // 200 100 10 20
    56. printList(L);
    57. //移除
    58. L.push_back(10000);
    59. L.push_back(10000);
    60. L.push_back(10000);
    61. L.push_back(10000);
    62. printList(L);
    63. L.remove(10000);//删除指定的值
    64. printList(L);
    65. //清空
    66. L.clear();
    67. printList(L);
    68. }
    69. int main() {
    70. test01();
    71. system("pause");
    72. return 0;
    73. }

    6. list 数据存取

    功能描述:

    对list容器中数据进行存取

    函数原型:

    1. front(); //返回第一个元素。
    2. back(); //返回最后一个元素

    总结:

    list容器中不可以通过[]或者at方式访问数据

    返回第一个元素 --- front

    返回最后一个元素 --- back

    示例

    list_main5.cpp

    1. #include
    2. using namespace std;
    3. #include
    4. //list容器 数据存取
    5. void test01()
    6. {
    7. list<int>L1;
    8. L1.push_back(10);
    9. L1.push_back(20);
    10. L1.push_back(30);
    11. L1.push_back(40);
    12. //L1[0] 不可以用[]访问list容器中的元素
    13. //L1.at(0) 不可以用at方式访问list容器中的元素
    14. //原因是list本质链表,不是用连续线性空间存储数据,迭代器也是不支持随机访问的
    15. cout << "第一个元素为:" << L1.front() << endl;
    16. cout << "最后一个元素为: " << L1.back() << endl;
    17. //验证迭代器是不支持随机访问的
    18. list<int>::iterator it = L1.begin();
    19. it++; //支持双向
    20. it--;
    21. //it = it + 1; //不支持随机访问
    22. }
    23. int main() {
    24. test01();
    25. system("pause");
    26. return 0;
    27. }

    7. list 反转和排序

    功能描述:

    将容器中的元素反转,以及将容器中的数据进行排序

    函数原型:

    1. reverse(); //反转链表
    2. sort(); //链表排序

    总结:

    反转 --- reverse

    排序 --- sort (成员函数)

    示例:

    list_main6.cpp

    1. #include
    2. using namespace std;
    3. #include
    4. #include
    5. //list容器反转和排序
    6. void printList(const list<int>&L)
    7. {
    8. for (list<int>::const_iterator it = L.begin(); it != L.end(); it++)
    9. {
    10. cout << *it << " ";
    11. }
    12. cout << endl;
    13. }
    14. void test01()
    15. {
    16. //反转
    17. list<int>L1;
    18. L1.push_back(20);
    19. L1.push_back(10);
    20. L1.push_back(50);
    21. L1.push_back(40);
    22. L1.push_back(30);
    23. cout << "反转前: " << endl;
    24. printList(L1);
    25. //反转
    26. L1.reverse();
    27. cout << "反转后: " << endl;
    28. printList(L1);
    29. }
    30. //自定义降序
    31. bool myCompare(int v1 ,int v2)
    32. {
    33. //降序 就让第一个数 > 第二个数
    34. return v1 > v2;
    35. }
    36. //排序
    37. void test02()
    38. {
    39. list<int>L1;
    40. L1.push_back(20);
    41. L1.push_back(10);
    42. L1.push_back(50);
    43. L1.push_back(40);
    44. L1.push_back(30);
    45. //排序
    46. cout << "排序前: " << endl;
    47. printList(L1);
    48. //所有不支持随机访问迭代器的容器,不可以用标准算法
    49. //不支持随机访问迭代器的容器,内部会提供对应一些算法
    50. //sort(L1.begin(), L1.end());
    51. L1.sort(); //默认排序规则 从小到大 升序
    52. cout << "排序后: " << endl;
    53. printList(L1);
    54. //降序
    55. L1.sort(myCompare);
    56. printList(L1);
    57. }
    58. int main() {
    59. //test01();
    60. test02();
    61. system("pause");
    62. return 0;
    63. }

    8. 排序案例

    案例描述:将Person自定义数据类型进行排序,Person中属性有姓名、年龄、身高

    排序规则:按照年龄进行升序,如果年龄相同按照身高进行降序

    list_main7.cpp

    1. #include
    2. using namespace std;
    3. #include
    4. #include
    5. //list容器 排序案例 对于自定义数据类型 做排序
    6. //按照年龄进行升序,如果年龄相同按照身高进行降序
    7. class Person
    8. {
    9. public:
    10. Person(string name, int age, int height)
    11. {
    12. this->m_Name = name;
    13. this->m_Age = age;
    14. this->m_Height = height;
    15. }
    16. string m_Name; //姓名
    17. int m_Age; //年龄
    18. int m_Height; // 身高
    19. };
    20. //指定排序规则
    21. bool comparePerson(Person& p1, Person& p2)
    22. {
    23. //按照年龄 升序
    24. if (p1.m_Age == p2.m_Age)
    25. {
    26. //年龄相同 按照身高降序
    27. return p1.m_Height > p2.m_Height;
    28. }
    29. else
    30. {
    31. return p1.m_Age < p2.m_Age;
    32. }
    33. }
    34. void test01()
    35. {
    36. listL; //创建容器
    37. //准备数据
    38. Person p1("刘备", 35, 175);
    39. Person p2("曹操", 45, 180);
    40. Person p3("孙权", 40, 170);
    41. Person p4("赵云", 25, 190);
    42. Person p5("张飞", 35, 160);
    43. Person p6("关羽", 35, 200);
    44. //插入数据
    45. L.push_back(p1);
    46. L.push_back(p2);
    47. L.push_back(p3);
    48. L.push_back(p4);
    49. L.push_back(p5);
    50. L.push_back(p6);
    51. for (list::iterator it = L.begin(); it != L.end(); it++)
    52. {
    53. cout << "姓名: " << (*it).m_Name << " 年龄: " << it->m_Age << " 身高: " << it->m_Height << endl;
    54. }
    55. //排序
    56. cout << "---------------------------------" << endl;
    57. cout << "排序后:" << endl;
    58. L.sort(comparePerson);
    59. for (list::iterator it = L.begin(); it != L.end(); it++)
    60. {
    61. cout << "姓名: " << (*it).m_Name << " 年龄: " << it->m_Age << " 身高: " << it->m_Height << endl;
    62. }
    63. }
    64. int main() {
    65. test01();
    66. system("pause");
    67. return 0;
    68. }

    总结:

    对于自定义数据类型,必须要指定排序规则,否则编译器不知道如何进行排序

    高级排序只是在排序规则上再进行一次逻辑规则制定,并不复杂

  • 相关阅读:
    高等数学(第七版)同济大学 总习题三(前10题) 个人解答
    流程引擎的架构设计
    Python基础内容训练12(异常处理)
    git常用命令
    在RT-Thread下为MPU手搓以太网MAC驱动-4
    【Pytorch with fastai】第 13 章 :卷积神经网络
    JDBC完成对数据库数据操作(增,删,改,查)
    数学建模圈养湖羊的空间利用率
    【蓝桥杯省赛真题44】Scratch像素画板 蓝桥杯少儿编程scratch图形化编程 蓝桥杯省赛真题讲解
    few shot object detection via feature reweight笔记
  • 原文地址:https://blog.csdn.net/m0_65554471/article/details/136187526