C++ STL list容器 链表

list基本概念:

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

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

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

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

优点:可以对任意位置进行快速插入或删除元素    

缺点:容器遍历速度,没有数组快,占用空间比数组大 

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

双向:每个结点  都有  前结点地址 和后结点地址  prev  next   

循环:最后一个结点记录第一个结点地址   第一个结点记录最后一个结点位置 不循环 则为NULL    

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

list的优点:

  采用动态存储分配,不会造成内存浪费和溢出 (数组vector动态拓展,可能造成内存浪费)

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

list的缺点:

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

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

总结:STL中  List(链表)  和  Vector(数组)  是两个最常被使用的容器,各有优缺点。   

list构造函数  

复制代码
 1 #include <iostream>
 2 #include <string>
 3 #include <list>
 4 using namespace std;
 5 //list构造函数
 6 /*     
 7     list<T> lst;            //list采用模板类实现,对象的默认构造形式
 8     list(beg,end);            //构造函数将[beg,end)区间的元素拷贝给本身
 9     list(n,elem);            //构造函数将n个elem拷贝给本身
10     list(const list& lst);    //拷贝构造函数
11 */
12 void printList(const list<int>& L)
13 {
14     for (list<int>::const_iterator it = L.begin(); it != L.end(); it++)
15     {
16         cout << *it << " ";
17     }
18     cout << endl;
19 }
20 void test()
21 {
22     //创建list容器
23     list<int>L1;
24     L1.push_back(10);
25     L1.push_back(20);
26     L1.push_back(30);
27     L1.push_back(40);
28     //遍历容器
29     printList(L1);//10 20 30 40
30     //区间方式构造
31     list<int>L2(L1.begin(), L1.end());
32     printList(L2);//10 20 30 40
33     //拷贝构造
34     list<int>L3(L2);
35     printList(L3);//10 20 30 40
36     //n个elem
37     list<int>L4(7, 100);
38     printList(L4);//100 100 100 100 100 100 100
39 }
40 int main()
41 {
42     test();
43     system("pause");
44     return 0;
45 }
复制代码

list赋值和交换 

list<int>L7 = {1,2,3,4,7,8};//赋值

-

复制代码
 1 #include <iostream>
 2 #include <string>
 3 #include <list>
 4 using namespace std;
 5 //给list容器进行赋值  以及交换list容器
 6 /*     
 7     assign(beg,end);                    //将[beg,end)区间中的数据拷贝赋值给本身
 8     assign(n,elem);                        //将n个elem拷贝赋值给本身
 9     list& operator=(const list& lst);    //重载等号操作符
10     swap(lst);                            //将lst与本身的元素互换
11 */
12 void printList(const list<int>& L)//打印输出  const限定数值不可修改
13 {
14     for (list<int>::const_iterator it = L.begin(); it != L.end(); it++)
15     {
16         cout << *it << " ";
17     }
18     cout << endl;
19 }
20 void test()
21 {
22     list<int>l1;
23     l1.push_back(10);
24     l1.push_back(20);
25     l1.push_back(30);
26     l1.push_back(40);
27     printList(l1);//10 20 30 40
28     
29     list<int>l2;
30     l2 = l1;        //operator= 赋值
31     printList(l2);//10 20 30 40
32 
33     list<int>l3;
34     l3.assign(l2.begin(), l2.end());
35     printList(l3);//10 20 30 40
36 
37     list<int>l4;
38     l4.assign(7, 100);
39     printList(l4);//100 100 100 100 100 100 100
40 }
41 //交换
42 void test2()
43 {
44     list<int>l1;
45     l1.push_back(10);
46     l1.push_back(20);
47     list<int>l2;
48     l2.assign(2, 100);
49     cout << "交换前:  " << endl;
50     printList(l1);
51     printList(l2);
52     
53     l1.swap(l2);
54     cout << "交换后:  " << endl;
55     printList(l1);
56     printList(l2);
57 }
58 int main()
59 {
60     //test();
61     test2();
62     system("pause");
63     return 0;
64 }
复制代码

list大小操作   

复制代码
 1 #include <iostream>
 2 #include <string>
 3 #include <list>
 4 using namespace std;
 5 //对list容器的大小进行操作
 6 /*     
 7     size();             //返回容器中元素的个数
 8     empty();            //判断容器是否为空
 9     resize(num);        //重新指定容器的长度为num,若容器变长,则以默认值填充新位置
10                         //如果容器变短,则末尾超出容器长度的元素被删除
11     resize(num,elem);   //重新指定容器的长度为num,若容器变长,则以elem值填充新位置
12                         //如果容器变短,则末尾超出容器长度的元素被删除
13 */
14 void printList(const list<int>& L)//防止误操作,修改內部值
15 {
16     for (list<int>::const_iterator it = L.begin(); it != L.end(); it++)
17     {
18         cout << *it << " ";
19     }
20     cout << endl;
21 }
22 void test()
23 {
24     list<int>L1;
25     L1.push_back(10);
26     L1.push_back(20);
27     L1.push_back(30);
28     L1.push_back(40);
29     printList(L1);// 10 20 30 40
30     if (L1.empty())
31     {
32         cout << "L1为空" << endl;
33     }
34     else
35     {
36         cout << "L1不为空" << endl;
37         cout << "L1的元素个数: " << L1.size() << endl;
38     }
39     //重新指定大小
40     L1.resize(10);//不限定 默认为0   L1.resize(10,1000); 此时限定为1000
41     printList(L1);// 10 20 30 40 0 0 0 0 0 0
42     L1.resize(2);//会删除后面的数据
43     printList(L1);//10 20
44 }
45 int main()
46 {
47     test();
48     system("pause");
49     return 0;
50 }
复制代码

list插入和删除    

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

list数据存取   

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

list容器反转和排序   

复制代码
 1 #include <iostream>
 2 #include <string>
 3 #include <list>
 4 #include <algorithm>
 5 using namespace std;
 6 //将容器中的元素反转,以及将容器中的数据进行排序
 7 /*     
 8     reverse();        //反转链表
 9     sort();           //链表排序
10 */
11 void printList(const list<int>& L)//const 防止误操作,修改內部值
12 {
13     for (list<int>::const_iterator it = L.begin(); it != L.end(); it++)
14     {
15         cout << *it << " ";
16     }
17     cout << endl;
18 }
19 bool myCompare(int v1, int v2)
20 {
21     //降序 让第一个数  >  第二个数
22     return v1 > v2;
23 }
24 void test()
25 {
26     //反转
27     list<int>L1;
28     L1.push_back(20);
29     L1.push_back(70);
30     L1.push_back(60);
31     L1.push_back(40);
32     cout << "反转前: " << endl;
33     printList(L1);//20 70 60 40
34     //反转后:
35     L1.reverse();
36     cout << "反转后" << endl;
37     printList(L1);//40 60 70 20
38     //排序
39     //sort(L1.begin(), L1.end());//报错,不支持随机访问迭代器的容器,不可以用标准算法
40     //不支持随机访问迭代器的容器,内部会提供对应一些算法
41     L1.sort();//默认从小到大  升序
42     cout << "排序后:" << endl;
43     printList(L1);//20 40 60 70
44     L1.sort(myCompare);//降序
45     printList(L1);//70 60 40 20
46 }
47 int main()
48 {
49     test();
50     system("pause");
51     return 0;
52 }
复制代码

排序案例:   

复制代码
 1 #include <iostream>
 2 #include <string>
 3 #include <list>
 4 using namespace std;
 5 //案例:排序
 6 /*
 7     将Person自定义数据类型进行排序,Person中属性有姓名、年龄、身高
 8     按照年龄进行升序,如果年龄相同按照身高进行降序
 9 */
10 class Person
11 {
12 public:
13     Person(string name, int age, int height)
14     {
15         this->m_Age = age;          //年龄
16         this->m_Height = height;    //身高
17         this->m_Name = name;        //姓名
18     }
19 public:
20     string m_Name;   //姓名
21     int m_Age;       //年龄
22     int m_Height;    //身高
23 };
24 //自定义: 指定排序规则
25 bool comparepPerson(Person& p1,Person& p2)
26 {
27     if (p1.m_Age == p2.m_Age)
28     {
29         return p1.m_Height > p2.m_Height;
30     }
31     else
32     {
33         return p1.m_Age < p2.m_Age;//升序
34     }
35 }
36 void test()
37 {
38     list<Person>L;
39     Person p1("刘一", 20, 180);
40     Person p2("王二", 25, 166);
41     Person p3("张三", 25, 195);
42     Person p4("李四", 33, 180);
43     L.push_back(p1);
44     L.push_back(p2);
45     L.push_back(p3);
46     L.push_back(p4);
47     for (list<Person>::iterator it = L.begin(); it != L.end(); it++)
48     {
49         cout << "姓名:" << (*it).m_Name << "  年龄:" << (*it).m_Age << "  身高:" << (*it).m_Height << endl;
50     }
51     //排序
52     L.sort(comparepPerson);
53     cout << "排序后:" << endl;
54     for (list<Person>::iterator it = L.begin(); it != L.end(); it++)
55     {
56         cout << "姓名:" << (*it).m_Name << "  年龄:" << (*it).m_Age << "  身高:" << (*it).m_Height << endl;
57     }
58 }
59 int main()
60 {
61     test();
62     system("pause");
63     return 0;
64 }
复制代码

posted on   廿陆  阅读(110)  评论(0编辑  收藏  举报

相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· .NET10 - 预览版1新功能体验(一)
点击右上角即可分享
微信分享提示