STL容器之list
【1】list简介
实质上,list容器就是一个双向链表,可以高效地进行插入、删除操作。
【2】list链表常用方法
(1)构造、赋值、清空、删除、插入、判空等
应用示例代码如下:
1 #include <list> 2 #include <iostream> 3 using namespace std; 4 5 // 打印链表数据信息 6 void print (const list<int> & tempList) 7 { 8 // cbegin 返回指向第一个元素的迭代器 9 // cend 返回指向最后一个元素之后位置的迭代器 10 list<int>::const_iterator cIter = tempList.cbegin(); 11 for (; cIter != tempList.cend(); ++cIter) 12 { 13 cout << (*cIter) << " "; 14 } 15 cout << endl; 16 } 17 18 void main() 19 { 20 // 构造函数(默认构造函数) 21 list<int> myList1; 22 23 // 构造函数(构建一个list,有10个元素,每个元素值都是10) 24 list<int> myList2(10, 10); 25 print(myList2); 26 27 // 拷贝构造函数 28 list<int> myList3(myList2); 29 print(myList3); 30 31 // 由区间内的值初始化list 32 int nArrayA[5] = {10, 20, 30, 40, 50}; 33 list<int> myList4(nArrayA, nArrayA + 5); 34 print(myList4); 35 36 // 赋值assign(input_iterator start, input_iterator end); 37 myList1.assign(nArrayA, nArrayA + 4); 38 print(myList1); 39 40 // 赋值assign(size_type num, const Type & val); 41 myList1.assign(10, 100); 42 print(myList1); 43 44 // 返回对最后一个元素的引用 45 cout << myList4.back() << endl; 46 47 // 返回对第一个元素的引用 48 cout << myList4.front() << endl; 49 50 // 清空链表clear 51 myList4.clear(); 52 cout << myList4.empty() << endl; 53 54 // 删除元素erase(iterator pos) 55 list<int>::iterator iter = myList1.begin(); 56 for (; iter != myList1.end(); ) 57 { 58 myList1.erase(iter++); 59 } 60 cout << myList1.empty() << endl; 61 62 // 删除元素erase(iterator start, iterator end) 63 myList3.erase(myList3.begin(), myList3.end()); 64 cout << myList3.empty() << endl; 65 66 // 插入元素insert(iterator pos, const TYPE& val) 67 myList1.insert(myList1.begin(), 110); 68 print(myList1); 69 70 // 插入元素insert(iterator pos, size_type num, const TYPE &val) 71 myList1.insert(myList1.begin(), 10, 23); 72 print(myList1); 73 74 // 插入元素insert(iterator pos, input_iterator start, input_iterator end) 75 int nArrayB[4] = {7, 8, 9, 10}; 76 myList1.insert(myList1.begin(), nArrayB, nArrayB + 4); 77 print(myList1); 78 79 system("pause"); 80 } 81 82 // run out: 83 /* 84 10 10 10 10 10 10 10 10 10 10 85 10 10 10 10 10 10 10 10 10 10 86 10 20 30 40 50 87 10 20 30 40 88 100 100 100 100 100 100 100 100 100 100 89 50 90 10 91 1 92 1 93 1 94 110 95 23 23 23 23 23 23 23 23 23 23 110 96 7 8 9 10 23 23 23 23 23 23 23 23 23 23 110 97 请按任意键继续. . . 98 */
(2)merge方法
请看如下最常见的崩溃代码:
代码1:链表1无序,链表2无序。
1 #include <list> 2 #include <iostream> 3 using namespace std; 4 5 // 打印链表数据信息 6 void print (const list<int> & tempList) 7 { 8 // cbegin 返回指向第一个元素的迭代器 9 // cend 返回指向最后一个元素之后位置的迭代器 10 list<int>::const_iterator cIter = tempList.cbegin(); 11 for (; cIter != tempList.cend(); ++cIter) 12 { 13 cout << (*cIter) << " "; 14 } 15 cout << endl; 16 } 17 18 void main() 19 { 20 // 构造函数(默认构造函数) 21 list<int> myList1, myList2; 22 // 赋值 23 myList1.assign(2, 3); 24 // 插入元素 25 int nArrayA[5] = {7, 8, 9, 10, 11}; 26 myList1.insert(myList1.begin(), nArrayA, nArrayA + 5); 27 // 追加元素 28 for (int i = 10; i < 15; ++i) 29 { 30 myList1.push_back(i + 2); 31 } 32 cout << "打印链表1的数据:" << endl; 33 print(myList1); 34 35 36 myList2.push_back(23); 37 myList2.push_back(20); 38 myList2.push_back(47); 39 myList2.push_back(36); 40 myList2.push_back(87); 41 cout << "打印链表2的数据:" << endl; 42 43 print(myList2); 44 45 myList1.merge(myList2); 46 cout << "合并后,打印链表1的数据:" << endl; 47 print(myList1); 48 cout << "合并后,打印链表2的数据:" << endl; 49 print(myList2); 50 51 system("pause"); 52 }
运行结果如下图:
代码2:链表1无序,链表2升序。
1 #include <list> 2 #include <iostream> 3 using namespace std; 4 5 // 打印链表数据信息 6 void print (const list<int> & tempList) 7 { 8 // cbegin 返回指向第一个元素的迭代器 9 // cend 返回指向最后一个元素之后位置的迭代器 10 list<int>::const_iterator cIter = tempList.cbegin(); 11 for (; cIter != tempList.cend(); ++cIter) 12 { 13 cout << (*cIter) << " "; 14 } 15 cout << endl; 16 } 17 18 void main() 19 { 20 // 构造函数(默认构造函数) 21 list<int> myList1, myList2; 22 // 赋值 23 myList1.assign(2, 3); 24 // 插入元素 25 int nArrayA[5] = {7, 8, 9, 10, 11}; 26 myList1.insert(myList1.begin(), nArrayA, nArrayA + 5); 27 // 追加元素 28 for (int i = 10; i < 15; ++i) 29 { 30 myList1.push_back(i + 2); 31 } 32 cout << "打印链表1的数据:" << endl; 33 print(myList1); 34 35 36 myList2.push_back(20); 37 myList2.push_back(23); 38 myList2.push_back(36); 39 myList2.push_back(37); 40 myList2.push_back(87); 41 cout << "打印链表2的数据:" << endl; 42 43 print(myList2); 44 45 myList1.merge(myList2); 46 cout << "合并后,打印链表1的数据:" << endl; 47 print(myList1); 48 cout << "合并后,打印链表2的数据:" << endl; 49 print(myList2); 50 51 system("pause"); 52 }
运行结果如下图:
代码3:链表1升序,链表2降序。
1 #include <list> 2 #include <iostream> 3 using namespace std; 4 5 // 打印链表数据信息 6 void print (const list<int> & tempList) 7 { 8 // cbegin 返回指向第一个元素的迭代器 9 // cend 返回指向最后一个元素之后位置的迭代器 10 list<int>::const_iterator cIter = tempList.cbegin(); 11 for (; cIter != tempList.cend(); ++cIter) 12 { 13 cout << (*cIter) << " "; 14 } 15 cout << endl; 16 } 17 18 void main() 19 { 20 // 构造函数(默认构造函数) 21 list<int> myList1, myList2; 22 // 赋值 23 myList1.assign(2, 3); 24 // 插入元素 25 int nArrayA[5] = {7, 8, 9, 10, 11}; 26 myList1.insert(myList1.end(), nArrayA, nArrayA + 5); 27 // 追加元素 28 for (int i = 10; i < 15; ++i) 29 { 30 myList1.push_back(i + 2); 31 } 32 cout << "打印链表1的数据:" << endl; 33 print(myList1); 34 35 myList2.push_back(87); 36 myList2.push_back(47); 37 myList2.push_back(36); 38 myList2.push_back(23); 39 myList2.push_back(20); 40 cout << "打印链表2的数据:" << endl; 41 42 print(myList2); 43 44 myList1.merge(myList2); 45 cout << "合并后,打印链表1的数据:" << endl; 46 print(myList1); 47 cout << "合并后,打印链表2的数据:" << endl; 48 print(myList2); 49 50 system("pause"); 51 }
运行结果如下图:
代码4:链表1降序,链表2降序。
1 #include <list> 2 #include <iostream> 3 using namespace std; 4 5 // 打印链表数据信息 6 void print (const list<int> & tempList) 7 { 8 // cbegin 返回指向第一个元素的迭代器 9 // cend 返回指向最后一个元素之后位置的迭代器 10 list<int>::const_iterator cIter = tempList.cbegin(); 11 for (; cIter != tempList.cend(); ++cIter) 12 { 13 cout << (*cIter) << " "; 14 } 15 cout << endl; 16 } 17 18 void main() 19 { 20 // 构造函数(默认构造函数) 21 list<int> myList1, myList2; 22 // 追加元素 23 for (int i = 15; i > 10; --i) 24 { 25 myList1.push_back(i + 2); 26 } 27 cout << "打印链表1的数据:" << endl; 28 print(myList1); 29 30 myList2.push_back(50); 31 myList2.push_back(49); 32 myList2.push_back(48); 33 myList2.push_back(47); 34 myList2.push_back(46); 35 cout << "打印链表2的数据:" << endl; 36 37 print(myList2); 38 39 myList1.merge(myList2); 40 cout << "合并后,打印链表1的数据:" << endl; 41 print(myList1); 42 cout << "合并后,打印链表2的数据:" << endl; 43 print(myList2); 44 45 system("pause"); 46 }
运行结果如下图:
代码5:链表1升序,链表2升序。
1 #include <list> 2 #include <iostream> 3 using namespace std; 4 5 // 打印链表数据信息 6 void print (const list<int> & tempList) 7 { 8 // cbegin 返回指向第一个元素的迭代器 9 // cend 返回指向最后一个元素之后位置的迭代器 10 list<int>::const_iterator cIter = tempList.cbegin(); 11 for (; cIter != tempList.cend(); ++cIter) 12 { 13 cout << (*cIter) << " "; 14 } 15 cout << endl; 16 } 17 18 void main() 19 { 20 // 构造函数(默认构造函数) 21 list<int> myList1, myList2; 22 // 赋值 23 myList1.assign(2, 3); 24 // 插入元素 25 int nArrayA[5] = {7, 8, 9, 10, 11}; 26 myList1.insert(myList1.end(), nArrayA, nArrayA + 5); 27 // 追加元素 28 for (int i = 10; i < 15; ++i) 29 { 30 myList1.push_back(i + 2); 31 } 32 cout << "打印链表1的数据:" << endl; 33 print(myList1); 34 35 myList2.push_back(20); 36 myList2.push_back(23); 37 myList2.push_back(36); 38 myList2.push_back(37); 39 myList2.push_back(87); 40 cout << "打印链表2的数据:" << endl; 41 42 print(myList2); 43 44 myList1.merge(myList2); 45 cout << "合并后,打印链表1的数据:" << endl; 46 print(myList1); 47 cout << "合并后,打印链表2的数据:" << endl; 48 print(myList2); 49 50 system("pause"); 51 }
运行结果如下图:
经过查资料及源码,发现问题是:
list链表合并merge方法注意事项:
1、合并的两个链表必须均默认升序的。即合并之前,两个链表就应该是由小到大顺序排列的。
2、合并完成后,被合并链表(myList2)数据元素被清空。
3、默认是按升序合并。比如上例4,若想按降序进行合并,需要指定降序。
修改后,如下代码:
1 #include <list> 2 #include <iostream> 3 using namespace std; 4 5 // 打印链表数据信息 6 void print (const list<int> & tempList) 7 { 8 // cbegin 返回指向第一个元素的迭代器 9 // cend 返回指向最后一个元素之后位置的迭代器 10 list<int>::const_iterator cIter = tempList.cbegin(); 11 for (; cIter != tempList.cend(); ++cIter) 12 { 13 cout << (*cIter) << " "; 14 } 15 cout << endl; 16 } 17 18 void main() 19 { 20 // 构造函数(默认构造函数) 21 list<int> myList1, myList2; 22 // 追加元素 23 for (int i = 15; i > 10; --i) 24 { 25 myList1.push_back(i + 2); 26 } 27 cout << "打印链表1的数据:" << endl; 28 print(myList1); 29 30 myList2.push_back(50); 31 myList2.push_back(49); 32 myList2.push_back(48); 33 myList2.push_back(47); 34 myList2.push_back(46); 35 cout << "打印链表2的数据:" << endl; 36 37 print(myList2); 38 39 myList1.merge(myList2, greater<int>()); 40 cout << "合并后,打印链表1的数据:" << endl; 41 print(myList1); 42 cout << "合并后,打印链表2的数据:" << endl; 43 print(myList2); 44 45 system("pause"); 46 }
按降序进行合并。前提必须两个链表均为降序有序排列。
(3)remove方法。删除链表中所有值为val的元素。
1 #include <list> 2 #include <iostream> 3 using namespace std; 4 5 // 打印链表数据信息 6 void print (const list<int> & tempList) 7 { 8 // cbegin 返回指向第一个元素的迭代器 9 // cend 返回指向最后一个元素之后位置的迭代器 10 list<int>::const_iterator cIter = tempList.cbegin(); 11 for (; cIter != tempList.cend(); ++cIter) 12 { 13 cout << (*cIter) << " "; 14 } 15 cout << endl; 16 } 17 18 void main() 19 { 20 // 构造函数(默认构造函数) 21 list<int> myList1; 22 myList1.assign(3, 12); 23 myList1.insert(myList1.end(), 3, 34); 24 for (int i = 15; i > 10; --i) 25 { 26 myList1.push_back(12); 27 } 28 for (int i = 10; i < 15; ++i) 29 { 30 myList1.push_front(i + 5); 31 } 32 cout << "打印链表的数据:" << endl; 33 print(myList1); 34 35 cout << "删除12后,打印链表数据:"; 36 myList1.remove(12); 37 print(myList1); 38 39 cout << "删除34后,打印链表数据:"; 40 myList1.remove(34); 41 print(myList1); 42 43 system("pause"); 44 } 45 46 // run out: 47 /* 48 打印链表的数据: 49 19 18 17 16 15 12 12 12 34 34 34 12 12 12 12 12 50 删除12后,打印链表数据:19 18 17 16 15 34 34 34 51 删除34后,打印链表数据:19 18 17 16 15 52 请按任意键继续. . . 53 */
(4)remove_if方法。用一元函数判断是否删除元素,若函数返回true,则删除该元素。
应用示例代码如下:
1 #include <list> 2 #include <iostream> 3 using namespace std; 4 5 // 打印链表数据信息 6 void print (const list<int> & tempList) 7 { 8 list<int>::const_iterator cIter = tempList.cbegin(); 9 for (; cIter != tempList.cend(); ++cIter) 10 { 11 cout << (*cIter) << " "; 12 } 13 cout << endl; 14 } 15 16 bool IsDel (int i) 17 { 18 return ((i % 2) == 1); 19 } 20 21 void main () 22 { 23 int myInts[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; 24 list<int> myList(myInts, myInts + 10); 25 26 cout << "打印链表数据元素:" << endl; 27 print(myList); 28 myList.remove_if(IsDel); 29 cout << "删除(val % 2 == 1)后打印链表数据元素:" << endl; 30 print(myList); 31 32 system("pause"); 33 } 34 35 // run out: 36 /* 37 打印链表数据元素: 38 1 2 3 4 5 6 7 8 9 10 39 删除(val % 2 == 1)后打印链表数据元素: 40 2 4 6 8 10 41 请按任意键继续. . . 42 */
(5)unique方法。移除重复元素。
1 #include <list> 2 #include <iostream> 3 using namespace std; 4 5 // 打印链表数据信息 6 void print (const list<int> & tempList) 7 { 8 list<int>::const_iterator cIter = tempList.cbegin(); 9 for (; cIter != tempList.cend(); ++cIter) 10 { 11 cout << (*cIter) << " "; 12 } 13 cout << endl; 14 } 15 16 void main() 17 { 18 list<int> myList; 19 myList.assign(5, 100); 20 for (int i = 0; i < 5; ++i) 21 { 22 myList.push_front(i + 2); 23 } 24 for (int i = 0; i < 5; ++i) 25 { 26 myList.push_back(10 + i); 27 } 28 myList.insert(myList.end(), 5, 45); 29 30 print(myList); 31 myList.unique(); // 移除重复元素 32 print(myList); 33 34 system("pause"); 35 } 36 37 // run out: 38 /* 39 6 5 4 3 2 100 100 100 100 100 10 11 12 13 14 45 45 45 45 45 40 6 5 4 3 2 100 10 11 12 13 14 45 41 请按任意键继续. . . 42 */
(6)splice 粘接方法的三种方式
应用示例代码如下:
1 #include <list> 2 #include <iostream> 3 using namespace std; 4 5 // 打印链表数据信息 6 void print (const list<int> & tempList) 7 { 8 list<int>::const_iterator cIter = tempList.cbegin(); 9 for (; cIter != tempList.cend(); ++cIter) 10 { 11 cout << (*cIter) << " "; 12 } 13 cout << endl; 14 } 15 16 void main() 17 { 18 list<int> myList1, myList2, myList3, myList4; 19 myList1.assign(5, 10); 20 myList2.push_front(22); 21 cout << "打印myList2的数据:" << endl; 22 print(myList2); 23 cout << "打印myList1的数据:" << endl; 24 print(myList1); 25 // 粘接方法1:splice(iterator pos, list& lst) 26 // 将myList1链表元素粘接到myList2链表的第一个位置(pos及其后元素均后移) 27 myList2.splice(myList2.begin(), myList1); 28 cout << "粘接后,打印myList2的数据:" << endl; 29 print(myList2); 30 cout << "粘接后,打印myList1的数据:" << endl; 31 print(myList1); 32 33 // 粘接方法2:splice(iterator pos, list& lst, iterator del) 34 // 将myList1链表元素从第二个开始粘接到myList3链表的第一个位置 35 myList1.assign(2, 11); 36 myList3.assign(2, 22); 37 cout << endl << "打印myList3的数据:" << endl; 38 print(myList3); 39 cout << "打印myList1的数据:" << endl; 40 print(myList1); 41 myList3.splice(myList3.begin(), myList1, ++myList1.begin()); 42 cout << "粘接后,打印myList3的数据:" << endl; 43 print(myList3); 44 cout << "粘接后,打印myList1的数据:" << endl; 45 print(myList1); 46 47 // 粘接方法3:splice(iterator pos, list& lst, iterator start, iterator end) 48 // 将myList1链表元素从第二个开始粘接到myList4链表的第二个位置 49 myList1.push_back(12); 50 myList1.push_back(13); 51 myList1.push_back(14); 52 myList1.push_back(15); 53 myList4.assign(4, 44); 54 cout << endl << "打印myList4的数据:" << endl; 55 print(myList4); 56 cout << "打印myList1的数据:" << endl; 57 print(myList1); 58 myList4.splice(++myList4.begin(), myList1, ++myList1.begin(), myList1.end()); 59 cout << "粘接后,打印myList4的数据:" << endl; 60 print(myList4); 61 cout << "粘接后,打印myList1的数据:" << endl; 62 print(myList1); 63 64 system("pause"); 65 } 66 67 // run out: 68 /* 69 打印myList2的数据: 70 22 71 打印myList1的数据: 72 10 10 10 10 10 73 粘接后,打印myList2的数据: 74 10 10 10 10 10 22 75 粘接后,打印myList1的数据: 76 77 78 打印myList3的数据: 79 22 22 80 打印myList1的数据: 81 11 11 82 粘接后,打印myList3的数据: 83 11 22 22 84 粘接后,打印myList1的数据: 85 11 86 87 打印myList4的数据: 88 44 44 44 44 89 打印myList1的数据: 90 11 12 13 14 15 91 粘接后,打印myList4的数据: 92 44 12 13 14 15 44 44 44 93 粘接后,打印myList1的数据: 94 11 95 请按任意键继续. . . 96 */
(7)swap方法。交换两个链表中的元素。
应用示例代码如下:
1 #include <list> 2 #include <iostream> 3 using namespace std; 4 5 // 打印链表数据信息 6 void print (const list<int> & tempList) 7 { 8 list<int>::const_iterator cIter = tempList.cbegin(); 9 for (; cIter != tempList.cend(); ++cIter) 10 { 11 cout << (*cIter) << " "; 12 } 13 cout << endl; 14 } 15 16 void main() 17 { 18 list<int> myList1, myList2; 19 for (int i = 0; i < 10; ++i) 20 { 21 myList1.push_back(rand() % 100); 22 } 23 for (int j = 0; j < 10; ++j) 24 { 25 myList2.push_back(rand() % 200); 26 } 27 cout << "打印myList1的数据:" << endl; 28 print(myList1); 29 cout << "打印myList2的数据:" << endl; 30 print(myList2); 31 myList1.swap(myList2); 32 cout << "交换后,打印myList1的数据:" << endl; 33 print(myList1); 34 cout << "交换后,打印myList2的数据:" << endl; 35 print(myList2); 36 37 system("pause"); 38 } 39 // run out: 40 /* 41 打印myList1的数据: 42 41 67 34 0 69 24 78 58 62 64 43 打印myList2的数据: 44 105 145 81 27 161 91 195 142 27 36 45 交换后,打印myList1的数据: 46 105 145 81 27 161 91 195 142 27 36 47 交换后,打印myList2的数据: 48 41 67 34 0 69 24 78 58 62 64 49 请按任意键继续. . . 50 */
(8)待续。。。。
【3】list与vector区别总结
数组与链表的优缺点;
数组:
优点:访问效率高,内存为连续的区域。
缺点:添加、删除操作效率低。大小固定,不适合动态存储(不方便动态添加)。
链表:
优点:一般内存不连续。添加、删除效率高。大小可变。
缺点:只能通过指针顺序访问,查询效率低。
Good Good Study, Day Day Up.
顺序 选择 循环 总结