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 }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· .NET10 - 预览版1新功能体验(一)