文章目录
============================ 【说明】 ===================================================
大家好,本专栏主要是跟学C++内容,自己学习了这位博主【 AI菌】的【C++21天养成计划】,讲的十分清晰,适合小白,希望给这位博主多点关注、收藏、点赞。
主要针对所学内容,通过自己的理解进行整理,希望大家积极交流、探讨,多给意见。后面也会给大家更新,其他一些知识。若有侵权,联系删除!共同维护网络知识权利!
=======================================================================================
写在前面
至此,我们了解了C++的基本语法,但是进一步学习C++,数据结构是必不可少的内容。 数据结构与算法决定了代码测存储方式,以及代码执行效率。
数据结构的重要性不言而喻, 关于数据结构的基本知识可以转至本人另一专栏====>【 数据结构】。同样也可以阅读博主【 AI菌】写的【 数据结构与算法】,比较通俗易懂,可以学习学习!
1、何为List类?
list
是顺序容器,也可以理解为顺序表。它是允许在表中任意位置进行插入与删除操作的数据结构。
list
顺序容器是双向链表,双向链表可以将所存储的元素存放在不同、不相关的位置。每个元素与前后元素链接,并且保持顺序性。
与单链表(forward_list)相似,只不过单链表只能向前遍历,因此单链表更小更高效。
与其他顺序容器(array、vector、queue
)相比较,list
在插入、删除和移动容器中已经获得迭代器的任何位置的元素时,表现更好。
list
和forward_list
相比其他顺序容器。主要缺点在于:无法通过索引直接得到元素。
2、List类——成员函数总结
2.1 构造函数
通过list类内部的多种重载构造函数,初始化list:
#include <iostream>
#include <list>
using namespace std;
int main ()
{
// 1.通过几种不同的(重载)构造函数初始化链表
list<int> first; // 整型空链表
list<int> second (4,100); // 四个值为100的链表
list<int> third (second.begin(),second.end()); // 链表3:值为链表2的内容
list<int> fourth (third); // 赋值链表3的链表4
// 2.迭代器可由数组创建,初始化链表
int array[] = {16,2,77,29};
list<int> fifth (array, array + sizeof(array) / sizeof(int) );
cout << "链表5的内容为: ";
for (list<int>::iterator it = fifth.begin(); it != fifth.end(); it++)
cout << *it << ' ';
return 0;
}
结果:
链表5的内容为: 16 2 77 29
2.2 重载运算符
使用重载运算符=
,可以在原有的链表容器中分配新的内容,替换当前内容,同时修改链表容器大小:
#include <iostream>
#include <list>
using namespace std;
int main ()
{
list<int> first (3); // 链表first 内容为0 0 0
list<int> second (5); // 链表second 内容为0 0 0 0 0
second = first;
first = list<int>();
std::cout << "Size of first: " << int (first.size()) <<endl;
std::cout << "Size of second: " << int (second.size()) <<endl;
return 0;
结果:
Size of first: 0
Size of second: 3
2.3 迭代器(iterater)
=> begin & end <=
(1) begin
begin()
返回list容器第一个元素。
(2) end
end()
返回list容器最后一个元素。
例:
#include <iostream>
#include <list>
using namespace std;
int main()
{
int array[] = {75,23,65,42,13};
list<int> mylist(array, array+5);
cout << "mylist contains:";
for (list<int>::iterator it=mylist.begin(); it != mylist.end(); ++it)
std::cout << ' ' << *it;
return 0;
}
结果:
mylist contains: 75 23 65 42 13
注:list::front
该成员函数返回的是,指向它的双向迭代器
=> rbegin & rend <=
(3) rbegin
rbegin()
:r
即代表reverse,颠倒,反向迭代器。rbegin则返回最后一个元素。
(4) rend
rend()
:r
即代表reverse,颠倒,反向迭代器。rbegin则返回第一个元素。
例:
#include <iostream>
#include <list>
using namespace std;
int main ()
{
list<int> mylist;
for (int i=1; i<=5; ++i)
mylist.push_back(i);
cout << "mylist backwards:";
for (list<int>::reverse_iterator rit=mylist.rbegin(); rit!=mylist.rend(); ++rit)
cout << ' ' << *rit;
return 0;
}
结果:
mylist backwards: 5 4 3 2 1
2.4 容量
=> empty <=
(1) empty
empty()
判断list容器是否为空。
#include <iostream>
#include <list>
using namespace std;
int main ()
{
list<int> mylist;
int sum (0);
for(int i=1;i<=10;++i)
mylist.push_back(i);
while (!mylist.empty())
{
sum += mylist.front();
mylist.pop_front();
}
std::cout << "total: " << sum ;
return 0;
}
结果:
total: 55
=> size & max_size <=
(2) size
size()
返回list容器中元素个数。
(3) max_size
size()
返回list容器中最大的元素。
例:
#include <iostream>
#include <list>
using namespace std;
int main ()
{
list<int> mylist;
for (int i=0; i<10; i++)
mylist.push_back(i);
cout << "size: " << mylist.size() << endl;
cout << "max_size: " << mylist.max_size() << endl;
return 0;
}
结果:
size: 10
max_size: 357913941
2.5 访问元素
=> front& back <=
(1) front
front()
返回list容器中第一个元素。
(2) back
back()
返回list容器中最后一个元素。
例:
#include <iostream>
#include <list>
using namespace std;
int main()
{
list<int> mylist;
for(int i=1; i<=5; ++i)
mylist.push_back(i);
cout<<"第一个元素是:"<<mylist.front()<<endl;
cout<<"最后一个元素是:"<<mylist.back()<<endl;
return 0;
}
结果:
第一个元素是:1
最后一个元素是:5
2.6 修改链表
=> push_front & push_back <=
(1) push_front
push_front()
在初始list容器第一个元素前增加一个数。
(2) push_back
push_back()
在初始list容器最后一个元素前增加一个数。
例:
#include <iostream>
#include <list>
using namespace std;
int main ()
{
list<int> mylist(2,100); // two ints with a value of 100
cout << "原始的list中各元素:";
for (list<int>::iterator it=mylist.begin(); it!=mylist.end(); ++it)
cout << ' ' << *it;
cout<<endl;
mylist.push_front(200);
mylist.push_front(300);
cout << "在list前插入元素后:";
for (list<int>::iterator it=mylist.begin(); it!=mylist.end(); ++it)
cout << ' ' << *it;
cout <<endl;
mylist.push_back(600);
cout << "在list后插入元素后:";
for (list<int>::iterator it=mylist.begin(); it!=mylist.end(); ++it)
cout << ' ' << *it;
return 0;
}
结果:
原始的list中各元素: 100 100
在list前插入元素后: 300 200 100 100
在list后插入元素后: 300 200 100 100 600
=> pop_front & pop_back <=
(3) pop_front
pop_front()
删除list容器中第一个元素,同时size减1。
(4) pop_back
pop_back()
删除list容器中最后一个元素,同时size减1。
例:
#include <iostream>
#include <list>
using namespace std;
int main ()
{
list<int> mylist;
for(int i=1;i<=5;i++)
mylist.push_back(i);
cout<<"原list中的元素:";
for(list<int>::iterator it=mylist.begin(); it!=mylist.end(); ++it )
cout<<*it<<" ";
cout<<endl;
mylist.pop_front();
cout << "删除list开头第一个元素后:";
for(list<int>::iterator it=mylist.begin(); it!=mylist.end(); ++it )
cout<<*it<<" ";
cout<<endl;
cout<<"list中元素个数:"<<mylist.size()<<endl;
mylist.pop_back();
cout<<"删除list最后一个元素:";
for(list<int>::iterator it=mylist.begin(); it!=mylist.end(); ++it )
cout<<*it<<" ";
cout<<endl;
cout<<"list中元素个数:"<<mylist.size()<<endl;
return 0;
}
结果:
原list中的元素:1 2 3 4 5
删除list开头第一个元素后:2 3 4 5
list中元素个数:4
删除list最后一个元素:2 3 4
list中元素个数:3
=> insert <=
(5) insert
insert()
在指定的位置前插入新元素。
#include <iostream>
#include <list>
#include <vector>
using namespace std;
int main ()
{
list<int> mylist;
list<int>::iterator it; //声明it为迭代器
for(int i=1; i<=5; ++i) mylist.push_back(i); // 1 2 3 4 5
it = mylist.begin();
++it; // it points now to number 2 ^
mylist.insert (it,10); // 1 10 2 3 4 5
// "it" still points to number 2 ^
mylist.insert (it,2,20); // 1 10 20 20 2 3 4 5
--it; // it points now to the second 20 ^
std::vector<int> myvector (2,30);
mylist.insert (it,myvector.begin(),myvector.end()); // 1 10 20 30 30 20 2 3 4 5
std::cout << "mylist contains:";
for (it=mylist.begin(); it!=mylist.end(); ++it)
cout << ' ' << *it;
return 0;
}
结果:
mylist contains: 1 10 20 30 30 20 2 3 4 5
=> erase <=
(6) erase
erase()
移除list容器中某个元素或某个范围内的元素。
#include <iostream>
#include <list>
using namespace std;
int main ()
{
list<int> mylist;
list<int>::iterator it1,it2;
// set some values:
for (int i=1; i<10; ++i) mylist.push_back(i*10);
// 10 20 30 40 50 60 70 80 90
it1 = it2 = mylist.begin(); // ^^
advance (it2,6); // ^ ^
++it1; // ^ ^
it1 = mylist.erase(it1); // 10 30 40 50 60 70 80 90
// ^ ^
it2 = mylist.erase(it2); // 10 30 40 50 60 80 90
// ^ ^
++it1; // ^ ^
--it2; // ^ ^
mylist.erase (it1,it2); // 10 30 60 80 90
// ^
cout << "mylist contains:";
for (it1=mylist.begin(); it1!=mylist.end(); ++it1)
cout << ' ' << *it1;
return 0;
}
结果:
mylist contains: 10 30 60 80 90
=> swap <=
(7) swap
list1.swap(list2)
list1容器与list2容器整体互换。
#include <iostream>
#include <list>
int main ()
{
std::list<int> first (3,100); // three ints with a value of 100
std::list<int> second (5,200); // five ints with a value of 200
first.swap(second);
std::cout << "first contains:";
for (std::list<int>::iterator it=first.begin(); it!=first.end(); it++)
std::cout << ' ' << *it;
std::cout << '\n';
std::cout << "second contains:";
for (std::list<int>::iterator it=second.begin(); it!=second.end(); it++)
std::cout << ' ' << *it;
return 0;
}
结果:
first contains: 200 200 200 200 200
second contains: 100 100 100
=> resize <=
(8) resize
resize()
调整list容器的大小,使容器包含n个元素。
若n<当前容器大小,则容器内的元素个数减少至n个元素,其他元素删除(销毁);
若n>当前容器大小,则容器在尾部补上所需元素,使容器元素个数达到n个,默认补0,若指定元素值,则list.resize(n,value)
,value
为指定元素值。
#include <iostream>
#include <list>
int main ()
{
std::list<int> mylist;
// set some initial content:
for (int i=1; i<10; ++i) mylist.push_back(i); //1 2 3 4 5 6 7 8 9
mylist.resize(5); //1 2 3 4 5
mylist.resize(8,100); //1 2 3 4 5 100 100 100
mylist.resize(12); //1 2 3 4 5 100 100 100 0 0 0 0
std::cout << "mylist contains:";
for (std::list<int>::iterator it=mylist.begin(); it!=mylist.end(); ++it)
std::cout << ' ' << *it;
return 0;
}
结果:
mylist contains: 1 2 3 4 5 100 100 100 0 0 0 0
=> clear <=
(9) clear
clear()
删除list容器所有元素,使容器size为0。
#include <iostream>
#include <list>
int main ()
{
std::list<int> mylist;
std::list<int>::iterator it;
mylist.push_back (100);
mylist.push_back (200);
mylist.push_back (300);
std::cout << "mylist contains:";
for (it=mylist.begin(); it!=mylist.end(); ++it)
std::cout << ' ' << *it;
std::cout << '\n';
mylist.clear(); //清空所有元素
mylist.push_back (1101);
mylist.push_back (2202);
std::cout << "mylist contains:";
for (it=mylist.begin(); it!=mylist.end(); ++it)
std::cout << ' ' << *it;
return 0;
}
结果:
mylist contains: 100 200 300
mylist contains: 1101 2202
2.7 其他
=> remove & remove_if <=
(1) remove
remove(value)
删除list容器中所有与value
相同的元素,并减小size值。
remove()
与上面所述的erase()
不一样,erase
作为迭代器删除元素,而remove()
则是依据元素值删除元素。
#include <iostream>
#include <list>
int main ()
{
int myints[]= {5,6,8,8,9,45,8};
std::list<int> mylist (myints,myints+7);
mylist.remove(8); //删除链表中所有为8的元素
std::cout << "mylist contains:";
for (std::list<int>::iterator it=mylist.begin(); it!=mylist.end(); ++it)
std::cout << ' ' << *it;
return 0;
}
结果:
mylist contains: 5 6 9 45
(2) remove_if
remove_if(condition)
依据condition
条件删除容器中部分元素。
#include <iostream>
#include <list>
// a predicate implemented as a function:
bool single_digit (const int& value) { return (value<10); }
// a predicate implemented as a class:
struct is_odd {
bool operator() (const int& value) { return (value%2)==1; }
};
int main ()
{
int myints[]= {15,36,7,17,20,39,4,1};
std::list<int> mylist (myints,myints+8); // 15 36 7 17 20 39 4 1
mylist.remove_if (single_digit); // 15 36 17 20 39
mylist.remove_if (is_odd()); // 36 20
std::cout << "mylist contains:";
for (std::list<int>::iterator it=mylist.begin(); it!=mylist.end(); ++it)
std::cout << ' ' << *it;
return 0;
}
结果:
mylist contains: 36 20
=> unique <=
(3) unique
list.unique()
删除容器中相同的元素,只保留最前面(第一个)元素。
list.unique(condition)
删除容器中不符合condition
的元素。
#include <iostream>
#include <cmath>
#include <list>
// 判断元素整数部分相同
bool same_integral_part (double first, double second)
{ return ( int(first)==int(second) ); }
// 判断相邻元素距离是否小于5
struct is_near {
bool operator() (double first, double second)
{ return (fabs(first-second)<5.0); }
};
int main ()
{
double mydoubles[]={ 12.15, 2.72, 73.0, 12.77, 3.14,
12.77, 73.35, 72.25, 15.3, 72.25 };
std::list<double> mylist (mydoubles,mydoubles+10);
mylist.sort(); // 2.72, 3.14, 12.15, 12.77, 12.77,
// 15.3, 72.25, 72.25, 73.0, 73.35
//版本1
mylist.unique(); // 2.72, 3.14, 12.15, 12.77
// 15.3, 72.25, 73.0, 73.35
//版本2
mylist.unique (same_integral_part); // 2.72, 3.14, 12.15
// 15.3, 72.25, 73.0
mylist.unique (is_near()); // 2.72, 12.15, 72.25
std::cout << "mylist contains:";
for (std::list<double>::iterator it=mylist.begin(); it!=mylist.end(); ++it)
std::cout << ' ' << *it;
return 0;
}
结果:
mylist contains: 2.72 12.15 72.25
=> sort <=
(4) sort
list.sort()
依据ASCII
码进行排序。
list.sort(comp)
依据自定义规则comp
排序。
#include <iostream>
#include <list>
#include <string>
#include <cctype>
// comparison, not case sensitive.
bool compare_nocase (const std::string& first, const std::string& second)
{
unsigned int i=0;
while ( (i<first.length()) && (i<second.length()) )
{
if (tolower(first[i])<tolower(second[i])) return true;
else if (tolower(first[i])>tolower(second[i])) return false;
++i;
}
return ( first.length() < second.length() );
}
int main ()
{
std::list<std::string> mylist;
std::list<std::string>::iterator it;
mylist.push_back ("one");
mylist.push_back ("two");
mylist.push_back ("Three");
mylist.sort();
std::cout << "mylist contains:";
for (it=mylist.begin(); it!=mylist.end(); ++it)
std::cout << ' ' << *it;
std::cout << '\n';
mylist.sort(compare_nocase);
std::cout << "mylist contains:";
for (it=mylist.begin(); it!=mylist.end(); ++it)
std::cout << ' ' << *it;
std::cout << '\n';
return 0;
}
结果:
mylist contains: Three one two
mylist contains: one Three two
=> reverse<=
(5) reverse
list.reverse()
颠倒list容器中的元素,注意区别上面swap()
成员函数的用法。
#include <iostream>
#include <list>
int main ()
{
std::list<int> mylist;
for (int i=1; i<10; ++i) mylist.push_back(i);
mylist.reverse();
std::cout << "mylist contains:";
for (std::list<int>::iterator it=mylist.begin(); it!=mylist.end(); ++it)
std::cout << ' ' << *it;
return 0;
}
结果:
mylist contains: 9 8 7 6 5 4 3 2 1
3、总结
最后,长话短说,大家看完就好好动手实践一下,切记不能三分钟热度、三天打鱼,两天晒网。大家也可以自己尝试写写博客,来记录大家平时学习的进度,可以和网上众多学者一起交流、探讨,我也会及时更新,来督促自己学习进度。一开始提及的博主【AI菌】,个人已关注,并订阅了相关专栏(对我有帮助的),希望大家觉得不错的可以点赞、关注、收藏。