C++ STL(七)容器_list

list(双向链表):是一个双向链表容器,可以高效的地进行插入和删除元素。

同前二种序列式容器相比,它不支持随机存取元素,不能使用数组[]和at方式进行访问。

它对元素的搜寻速度是所有容器中最慢的。

所需头文件:#include<list>

构造函数:

 1     list<int> listA; //构造个空的list
 2     list<int> listB(5); //定义有5个int元素的list (listB={0,0,0,0,0})
 3     list<int> listC(5,1);//定义有5个int元素的list,每个元素的值为1 (listC={1,1,1,1,1})
 4     list<int> listD(listC); //通过listC拷贝构造一个listD (listD={1,1,1,1,1})
 5     int nArray[] = {1,2,3};
 6     int nLeng = sizeof(nArray)/sizeof(int);
 7     list<int> listE(nArray, nArray+nLeng); //通过数组拷贝构造一个listE (listE={1,2,3})
 8     //使用迭代器构造
 9     list<int> listDD;
10     listDD.push_back(1);
11     listDD.push_back(2);
12     listDD.push_back(3);
13     listDD.push_back(4);
14     listDD.push_back(5);
15     list<int> dIt(listDD.begin(),listDD.end()); //正向迭代器方式构造list (dIt={1,2,3,4,5})
16     list<int> dRit(listDD.rbegin(), listDD.rend()); //反向迭代器方式构造list (dRit={5,4,3,2,1})
17 
18     //注意:
19     //begin()与end()配套使用.   正向迭代器
20     //rbegin()与rend()配套使用. 反向迭代器
21     //begin()返回指向list第一个元素的迭代器  end()返回指向list最后一个元素+1位置的迭代器
22     //rbegin()返回指向list最后一个元素的迭代器  rend()返回指向list第一个元素-1位置的迭代器
23 
24     return;
构造函数

获取大小:

empty()  返回是否为空

size()     返回大小

max_size()  返回所能存储的最大元素个数,这是由系统自动定义的值

resize()    重新设置size,如果变长,变长的元素部份使用默认值,变短就删除多余的元素

 1     list<int> listA;
 2     bool bEmpty = listA.empty(); //bEmpty = true 是否为空
 3     listA.push_back(1);
 4     listA.push_back(2);
 5     bEmpty = listA.empty(); //bEmpty = false
 6     int nLeng = listA.size();  //nLeng = 2  容器大小
 7     int nMaxSize = listA.max_size(); //nMaxSize = 1073741823 所能存储的最大元素个数,这是由系统自动定义的值
 8 
 9     //resize重新设置size,如果变长,变长的元素部份使用默认值,变短就删除多余的元素.
10     listA.resize(10);
11     nLeng = listA.size(); //nLeng = 10 
12     listA.resize(1);
13     nLeng = listA.size(); //nLeng = 1
14 
15     //注意:deque没有deque中的capacity和reserdE方法
16     return;
获取大小

赋值操作:

注意不能使用数组[]和at方式进行访问

 1     //使用assign()方式赋值
 2     list<int> listC;
 3     //void assign(size_type _Count, const _Ty& _listAl)
 4     listC.assign(2,6); //给listC赋值二个int型元素,元素值为6 (listC={6,6})
 5     //void assign(_Iter _First, _Iter _Last)
 6     list<int> listD;
 7     listC.assign(listD.begin(),listD.end()); //使用迭代器方式把listD中所有元素赋值给listC (listC={})
 8 
 9     //使用swap()交换方式赋值
10     list<int> listE(2,3);
11     list<int> listF(4,4);
12     listE.swap(listF); //ListE = {4,4,4,4} listF = {3,3}
13 
14     return;
assign()赋值

增加元素操作:

push_front()   往头部插入一个元素

push_back()  往末尾插入一个元素

insert()  往任意位置插入一个元素,指定位置或者指定区间进行插入,第一个参数都是个迭代器。返回值是指向新元素的迭代器

 1     list<int> listA;
 2     //使用push_front()方式,头部插入元素
 3     listA.push_front(1); //listA = {1}
 4     //使用push_back()方式,末尾插入元素
 5     listA.push_back(2); //listA = {1,2}
 6 
 7     //使用insert()方式插入元素, 第一个参数都是迭代器,返回值是指向新元素的迭代器
 8     list<int>::iterator it;
 9     //iterator insert(const_iterator _Where, const _Ty& _listAl) 指定位置插入
10     it = listA.insert(listA.begin(),2); //往begin()之前插入一个int元素2 (listA={2,1,2}) 此时it指向第一个元素2
11     //void insert(const_iterator _Where, size_type _Count, const _Ty& _listAl) 指定位置插入
12     it = listA.insert(listA.end(),2,3);//往end()之前插入2个int元素3 (listA={2,1,2,3,3}) 此时it指向最后一个元素3
13     //void insert(const_iterator _Where, _Iter _First, _Iter _Last) 指定区间插入
14     list<int> listB(3,6);
15     it = listA.insert(listA.end(),listB.begin(),listB.end()); //把listB中所有元素插入到listA的end()之前 (listA={2,1,2,3,3,6,6,6})
16     //此时*it=6,指向最后一个元素值为6的元素位置
push_front()和push_back()和insert()

删除元素操作:

pop_front() 从头部删除一个元素

pop_back()  从末尾删除一个元素

erase()  从任意位置删除一个元素,指定位置或者指定区间进行删除,第一个参数都是个迭代器。返回值是指向删除后的下一个元素的迭代器

clear()   清除中所有元素, size=0

 1     list<int> listA;
 2     listA.push_back(1);
 3     listA.push_back(2);
 4     listA.push_back(3);
 5     listA.push_back(4);
 6     listA.push_back(5);
 7     //使用pop_front()方式删除头部元素
 8     listA.pop_front(); //listA={2,3,4,5}
 9     //使用pop_back()方式删除末尾元素
10     listA.pop_back(); //listA={2,3,4}
11     //使用erase()方式删除元素,第一个参数都是迭代器,返回值是指向删除后的下一个元素的迭代器
12     list<int>::iterator it;
13     //iterator erase(const_iterator _Where) 指定位置删除
14     it = listA.erase(listA.begin()); //删除Where位置的元素 (listA={3,4}) 此时it指向元素3
15     //void _Reverse(pointer _First, pointer _Last) 指定区间删除
16     it = listA.erase(listA.begin(),listA.end()); //把begin()到end()之间的所有元素删除 (listA={})
17     //此时list中己经没有元素了,迭代器指向的下一个元素就是end()
18 
19     //使用clear()方式清除所有元素,size变为0
20     list<int> listB(5,5);
21     listB.clear(); //(listB={},size=0)
22 
23     return;
pop_front()和pop_back()和erase()和clear()

遍历元素操作:

注意:list不支持随机访问,只能通过迭代器进行遍历

 1     list<int> dd;
 2     dd.push_back(1);
 3     dd.push_back(2);
 4     dd.push_back(3);
 5     dd.push_back(4);
 6     dd.push_back(5);
 7 
 8     //使用正向迭代器方式遍历
 9     list<int>::iterator it;
10     it = dd.begin();
11     for (it; it!=dd.end(); ++it)
12     {
13         cout<<*it<<" ";
14     }
15     cout<<endl;
16     //使用反向迭代器方式遍历
17     list<int>::reverse_iterator rit;
18     rit = dd.rbegin();
19     for (rit; rit!=dd.rend(); ++rit)
20     {
21         cout<<*rit<<" ";
22     }
23 
24     return;
迭代器方式遍历

释放内存操作:

注意:除了vector以外,其它容器使用clear都会自动释放内存,不需要使用空的容器进行swap

小练习题:

定义一个int型vector,包含1,3,2,3,3,3,4,3,5,3 

删除容器中所有等于3的元素,然后剩余元素{1,2,4,5} 每二个元素之间插入6个6

使用vector deque list, 比较三种序列式容器在随机插入和删除上的性能效率

1. 先声明相关变量

1     int nArray[] = {1,3,2,3,3,3,4,3,5,3};
2     int nLeng = sizeof(nArray)/sizeof(int);
3     double run_time;
4     _LARGE_INTEGER time_start;  //开始时间
5     _LARGE_INTEGER time_over;   //结束时间
6     double dqFreq;      //计时器频率
7     LARGE_INTEGER f;    //计时器频率
8     QueryPerformanceFrequency(&f);
9     dqFreq=(double)f.QuadPart;
相关变量

2. vector代码

 1     //vector
 2     QueryPerformanceCounter(&time_start);   //计时开始
 3 
 4     vector<int> vA(nArray,nArray+nLeng);
 5     vector<int>::iterator itA = vA.begin();
 6     while (itA!=vA.end())
 7     {
 8         if(*itA == 3)
 9         {
10             itA = vA.erase(itA);
11         }else
12         {
13             ++itA;
14         }
15     }
16 
17     QueryPerformanceCounter(&time_over);    //计时结束
18     //乘以1000000把单位由秒化为微秒,精度为1000 000/(cpu主频)微秒
19     run_time=1000000*(time_over.QuadPart-time_start.QuadPart)/dqFreq;
20     printf("vector删除花费时间:%fus\n",run_time);
21 
22     QueryPerformanceCounter(&time_start);   //计时开始
23     //剩余元素{1,2,4,5} 每二个元素之间插入6个6
24     itA = vA.begin();
25     while (++itA!=vA.end())
26     {
27         for (int i=0; i<6; i++)
28         {
29             itA = vA.insert(itA,6);
30         }
31         itA += 6;
32     }
33     QueryPerformanceCounter(&time_over);    //计时结束
34     //乘以1000000把单位由秒化为微秒,精度为1000 000/(cpu主频)微秒
35     run_time=1000000*(time_over.QuadPart-time_start.QuadPart)/dqFreq;
36     printf("vector插入花费时间:%fus\n",run_time);
37 
38 
39     //deque
40     QueryPerformanceCounter(&time_start);   //计时开始
41 
42     deque<int> dB(nArray,nArray+nLeng);
43     deque<int>::iterator itB = dB.begin();
44     while (itB!=dB.end())
45     {
46         if(*itB == 3)
47         {
48             itB = dB.erase(itB);
49         }else
50         {
51             ++itB;
52         }
53     }
54     QueryPerformanceCounter(&time_over);    //计时结束
55     run_time=1000000*(time_over.QuadPart-time_start.QuadPart)/dqFreq;
56     printf("deque删除花费时间:%fus\n",run_time);
57 
58     QueryPerformanceCounter(&time_start);   //计时开始
59     itB = dB.begin();
60     while (++itB!=dB.end())
61     {
62         for (int i=0; i<6; i++)
63         {
64             itB = dB.insert(itB,6);
65         }
66         itB += 6;
67     }
68 
69     QueryPerformanceCounter(&time_over);    //计时结束
70     run_time=1000000*(time_over.QuadPart-time_start.QuadPart)/dqFreq;
71     printf("deque插入花费时间:%fus\n",run_time);
vector

3.deque代码

 1 //deque
 2     QueryPerformanceCounter(&time_start);   //计时开始
 3 
 4     deque<int> dB(nArray,nArray+nLeng);
 5     deque<int>::iterator itB = dB.begin();
 6     while (itB!=dB.end())
 7     {
 8         if(*itB == 3)
 9         {
10             itB = dB.erase(itB);
11         }else
12         {
13             ++itB;
14         }
15     }
16     QueryPerformanceCounter(&time_over);    //计时结束
17     run_time=1000000*(time_over.QuadPart-time_start.QuadPart)/dqFreq;
18     printf("deque删除花费时间:%fus\n",run_time);
19 
20     QueryPerformanceCounter(&time_start);   //计时开始
21     itB = dB.begin();
22     while (++itB!=dB.end())
23     {
24         for (int i=0; i<6; i++)
25         {
26             itB = dB.insert(itB,6);
27         }
28         itB += 6;
29     }
30 
31     QueryPerformanceCounter(&time_over);    //计时结束
32     run_time=1000000*(time_over.QuadPart-time_start.QuadPart)/dqFreq;
33     printf("deque插入花费时间:%fus\n",run_time);
deque

4.list代码

 1     //list
 2     QueryPerformanceCounter(&time_start);
 3 
 4     list<int> listC(nArray,nArray+nLeng);
 5     list<int>::iterator itC = listC.begin();
 6     while (itC!=listC.end())
 7     {
 8         if(*itC == 3)
 9         {
10             itC = listC.erase(itC);
11         }else
12         {
13             ++itC;
14         }
15     }
16     QueryPerformanceCounter(&time_over);    //计时结束
17     run_time=1000000*(time_over.QuadPart-time_start.QuadPart)/dqFreq;
18     printf("list删除花费时间:%fus\n",run_time);
19 
20     QueryPerformanceCounter(&time_start);
21     itC = listC.begin();
22     while (++itC!=listC.end())
23     {
24         for (int i=0; i<6; i++)
25         {
26             listC.insert(itC,6);
27         }
28     }
29 
30     QueryPerformanceCounter(&time_over);
31     run_time=1000000*(time_over.QuadPart-time_start.QuadPart)/dqFreq;
32     printf("list插入花费时间:%fus\n",run_time);
list

输出结果:

 

ps:这里因为计算的时间片很短,使用了高精度计时器方便比较

总结:从输出结果可以看出在任意位置(除了头部和尾部)删除和插入元素上,list效率最高,vector和deque差不多

posted @ 2019-12-26 15:50  SmallOverFllow  阅读(202)  评论(0编辑  收藏  举报