第一部分  基本用法

  头文件  #include <vector>

  • vector<int> v;    //创建一个vector变量v+存放int型数据。
  • vector<int> v(v1);   // vector变量v+存放int型数据+初始化为v1
  • vector<int> v(ary + 2, ary + 5);   //创建一个vector变量v+存放int型数据+
  • vector<int> v(10, 1);   //创建一个vector变量+存放10个int型数据+每个数据的初始值都设为1。
  • vector<int>::iterator iter;   //对vector中的元素进行遍历。
    for(iter = vec.begin(); iter != vec.end(); iter++) 

    //. . . . . . . 
    }
  • vector<T1>::iterator相关的方法有: 
    begin():用来获得一个指向vector第一个元素的指针 
    end():用来获得一个指向vector最后一个元素之后的那个位置的指针,注意不是指向最后一个元素。 
    erase(vector<T1>::iterator):用来删除作为参数所传入的那个iterator所指向的那个元素。
  • 更多实例,请参考:https://blog.csdn.net/sum_tw/article/details/54891142
vector<Elem> v;
vector<Elem> v(v1);
vector<Elem> v(begin, end);
vector<Elem> v(n, elem);
创建一个空的vector
复制一个v1的vector
创建一个[begin, end)区间的vector
创建一个含有n个elem的vector
void assign(n, elem);
void assign(begin, end);
将n个elem的拷贝复制给v
将[begin, end)区间的值赋给v
reference at(size_type pos); 传回索引pos所指的数据
reference front(); 
const_reference front() const;
传回第一个数据
reference back(); 
const_reference back() const;
传回最后一个数据
iterator begin(); 
const_iterator begin() const;
reverse_iterator rbegin(); 
const_reverse_iterator rbegin() const;
返回指向第一个元素的地址

传回一个逆向队列的第一个数据的地址
iterator end(); 
const_iterator end() const;
reverse_iterator rend(); 
const_reverse_iterator rend() const;
指向迭代器中的最后一个数据的下一个位置的地址

传回一个逆向队列的最后一个数据的下一个位置的地址

v.insert(pos, elem);


v.insert(pos, n, elem);
v.insert(pos, begin, end);

在pos位置插入一个elem拷贝   //示例:v1.insert(v1.begion(),3)

                                               //标红部分必须相同。

在pos位置插入n个elem拷贝
在pos位置插入[begin, end)的数据
v.erase(pos);
v.erase(v.begin(), v.end());
删除pos位置的数据
删除[v.begin(), v.end())的数据
bool empty() const; 判断容器是否为空
size_type size() const; 返回容器中实际数据的个数
void push_back(const T& x); 在容器尾部加入一个数据
void pop_back(); 删除最后一个数据
void clear(); 清空容器
v1.swap(v2);
swap(v1, v2);
将v1和v2互换
























笔试-STL-Vector

第二部分  常见的考题

list和vector

  vector是动态空间是随着元素的加入,它的内部机制会自动的扩充空间来容纳新的元素。因此,vector的运用对于内存的合理利用与运用的灵活性有很大的帮助,我们不必因为害怕空间不足而一开始就开辟一块很大的内存。
vector

一个动态增长的数组,里面有一个指针指向一片连续的内存空间,当空间装不下的时候会自动申请一片更大的空间(空间配置器)将原来的数据拷贝到新的空间,然后就会释放旧的空间。当删除的时候空间并不会被释放只是清空了里面的数据。

vector维护的是一个连续线性空间,所以vector支持随机访问。

对vector的任何操作一旦引起了空间的重新配置,指向原vector的所有迭代器就会都失效了。原因:在vector的动态增加大小的时候,并不是在原有的空间上持续新的空间(无法保证原空间的后面还有可供配置的空间),而是以原大小的两倍另外配置一块较大的空间,然后将原内容拷贝过来,并释放原空间。这也是程序员易犯的一个错误。

vector由于数组的增长只能向前,所以也只提供了后端插入和后端删除, 也就是push_back和pop_back。当然在前端和中间要操作数据也是可以的, 用insert和erase,但是前端和中间对数据进行操作必然会引起数据块的移动, 这对性能影响是非常大的。最大的优势就是随机访问的能力。


array


array是静态空间一旦配置了就不能改变大小,如果要扩大或缩小容量的话,就要把数据搬到新大小的数组里面,然后再把原来的空间释放还给系统。


1.说说std::vector的底层(存储)机制。

 vector就是一个动态数组,里面有一个指针指向一片连续的内存空间,当空间不够装下数据时,会自动申请另一片更大的空间(一般是增加当前容量的50%或100%),然后把原来的数据拷贝过去,接着释放原来的那片空间;当释放或者删除里面的数据时,其存储空间不释放,仅仅是清空了里面的数据。

2.std::vector的自增长机制。

当已经分配的空间不够装下数据时,分配双倍于当前容量的存储区,把当前的值拷贝到新分配的内存中,并释放原来的内存。

3.具体说明STL如何实现vector

vector的内部是使用动态数组的方式来实现的,如果动态数组的内部实现不够用,就要动态的重新分配内存。然后把原数组的内容拷贝过去。
4.vector中begin和end函数返回的是什么?

begin返回的是第一个元素的迭代器,end返回的是最后一个元素后面位置的迭代器。

5.为什么vector的插入操作可能会导致迭代器失效?

vector动态增加大小时,并不是在原空间后增加新的空间,而是以原大小的两倍在另外配置一片较大的新空间,然后将内容拷贝过来,并释放原来的空间。由于操作改变了空间,所以迭代器失效。

6.说说std::list的底层(存储)机制。

以结点为单位存放数据,结点的地址在内存中不一定连续,每次插入或删除一个元素,就配置或释放一个元素空间

7.list自带排序函数的排序原理。

将前两个元素合并,再将后两个元素合并,然后合并这两个子序列成4个元素的子序列,重复这一过程,得到8个,16个,...,子序列,最后得到的就是排序后的序列。时间复杂度:O(nlgn)

8.什么情况下用vector,什么情况下用list。

vector可以随机存储元素(即可以通过公式直接计算出元素地址,而不需要挨个查找),但在非尾部插入删除数据时,效率很低,适合对象简单,对象数量变化不大,随机访问频繁。

list不支持随机存储,适用于对象大,对象数量变化频繁,插入和删除频繁。

9.vector插入删除和list有什么区别?

vector插入和删除数据,需要对现有数据进行复制移动,如果vector存储的对象很大或者构造函数很复杂,则开销较大,如果是简单的小数据,效率优于list。

list插入和删除数据,需要对现有数据进行遍历,但在首部插入数据,效率很高。

10.vector和list的区别

关键字:vector、list、数组、双向链表、内存空间连续性、存取、插入、删除、搜索、复杂度。

vector和数组类似,它拥有一段连续的内存空间,并且起始地址不变,因此它能非常好的支持随机存取(即使用[]操作符访问其中的元素),但由于它的内存空间是连续的,所以在中间进行插入和删除会造成内存块的拷贝(复杂度是O(n)),另外,当该数组后的内存空间不够时,需要重新申请一块足够大的内存并进行内存的拷贝。这些都大大影响了vector的效率。

list是由数据结构中的双向链表实现的,因此它的内存空间可以是不连续的。因此只能通过指针来进行数据的访问,这个特点使得它的随机存取变的非常没有效率,需要遍历中间的元素,搜索复杂度O(n),

vector和数组的关系/list和链表的关系:

  • vector和数组类似。

  • list是由双向链表实现的。

从存储空间的连贯性上看:

  • vector:拥有连续的内存空间

从访问/遍历的角度看:

  • list是由数据结构中的双向链表实现的,因此它的内存空间可以是不连续的。因此只能通过指针来进行数据的访问,这个特点使得它的随机存取变的非常没有效率,需要遍历中间的元素,搜索复杂度O(n)。——list没有提供[]操作符的重载。

  • vector支持随机的存取

从删除/插入的角度看:

  • list可以以很好的效率支持任意地方的删除和插入。——来自双链表结构

  • vector进行元素的插入和删除的操作时间复杂度是O(n)。

11.如何选择使用vector或dequeue

一般情况下使用vector,在需要从首尾两端进行插入或删除操作的时候需要选择dequeue.

12.vector中erase方法与algorithn中的remove方法区别

  • vector中erase方法真正删除了元素,迭代器不能访问了
  • remove只是简单地将元素移到了容器的最后面,迭代器还是可以访问到。因为algorithm通过迭代器进行操作,不知道容器的内部结构,所以无法进行真正的删除。

13.list - 擅长插入删除的链表

list<string>Milkshakes; list<int> Scores;

push_back, pop_backpush_front. pop_front

list是一个双向链表的实现。 为了提供双向遍历的能力,list要比一般的数据单元多出两个指向前后的指针。一个使用iterator来删除元素的例子 :
     list<string> stringList; 
     list<string>::iterator iter; 
     advance(iter, 5); //将iterator指向stringList的第五个元素 
     stringList.erase(iterator);//删除 

那么删除操作进行以后,传入erase()方法的iterator指向哪里了呢?它指向了删除操作前所指向的那个元素的后一个元素。

14.deque - 拥有vector和list两者优点的双端队列

15.list、vector、deque模板的总结 比较和一般使用准则 .

这三个模板都属于序列类模板,可以看到他们有一些通用方法 :

  •      size():得到容器大小

  •      begin():得到指向容器内第一个元素的指针(这个指针的类型依容器的不同而不同) 

  •     end():得到指向容器内最后一个元素之后一个位置的指针 

  •     erase():删除传入指针指向的那个元素 

  •     clear():清除所有的元素 

  •     ==运算符:判断两个容器是否相等 

  •      =运算符:用来给容器赋值

各自的特点 

vector模板的数据在内存中连续的排列,所以随机存取元素(即通过[]运算符存取)的速度最快,这一点和数组是一致的。同样由于它的连续排列,所以它在除尾部以外的位置删除或添加元素的速度很慢,在使用vector时,要避免这种操作。 
list模板的数据是链式存储,所以不能随机存取元素。它的优势在于任意位置添加 删除元素的速度。 
deque模板是通过链接若干片连续的数据实现的,所以均衡了以上两个容器的特点

   

相关文章:

  • 2022-03-06
  • 2022-12-23
  • 2022-12-23
  • 2021-06-05
  • 2021-09-22
  • 2021-11-26
  • 2021-09-08
猜你喜欢
  • 2021-08-28
  • 2022-12-23
  • 2021-08-09
  • 2021-07-19
  • 2021-06-19
  • 2022-01-11
相关资源
相似解决方案