zoukankan      html  css  js  c++  java
  • 备战秋招,面试知识点总结:容器和算法(二)

    map和set有什么区别,分别又是怎么实现的?

    map和set都是C++的关联容器,其底层实现都是红黑树(RB-Tree)。由于 map 和set所开放的各种操作接口,RB-tree 也都提供了,所以几乎所有的 map 和set的操作行为,都只是转调 RB-tree 的操作行为。

    map和set区别在于:

    (1)map中的元素是key-value(关键字—值)对:关键字起到索引的作用,值则表示与索引相关联的数据;Set与之相对就是关键字的简单集合,set中每个元素只包含一个关键字。

    (2)set的迭代器是const的,不允许修改元素的值;map允许修改value,但不允许修改key。其原因是因为map和set是根据关键字排序来保证其有序性的,如果允许修改key的话,那么首先需要删除该键,然后调节平衡,再插入修改后的键值,调节平衡,如此一来,严重破坏了map和set的结构,导致iterator失效,不知道应该指向改变前的位置(指要更改键值的这个迭代器,不知道应该指向哪),还是指向改变后的位置。所以STL中将set的迭代器设置成const,不允许修改迭代器的值;而map的迭代器则不允许修改key值,允许修改value值。

    (3)map支持下标操作,set不支持下标操作。map可以用key做下标,map的下标运算符[ ]将关键码作为下标去执行查找,如果关键码不存在,则插入一个具有该关键码和mapped_type类型默认值的元素至map中,因此下标运算符[ ]在map应用中需要慎用,const_map不能用,只希望确定某一个关键值是否存在而不希望插入元素时也不应该使用,mapped_type类型没有默认值也不应该使用。如果find能解决需要,尽可能用find。

    STL的allocaotr

    STL的分配器用于封装STL容器在内存管理上的底层细节。在C++中,其内存配置和释放如下:

    new运算分两个阶段:(1)调用::operator new配置内存;(2)调用对象构造函数构造对象内容

    delete运算分两个阶段:(1)调用对象希构函数;(2)调用::operator delete释放内存

    为了精密分工,STL allocator将两个阶段操作区分开来:内存配置有alloc::allocate()负责,内存释放由alloc::deallocate()负责;对象构造由::construct()负责,对象析构由::destroy()负责。

    同时为了提升内存管理的效率,减少申请小内存造成的内存碎片问题,SGI STL采用了两级配置器,当分配的空间大小超过128B时,会使用第一级空间配置器;当分配的空间大小小于128B时,将使用第二级空间配置器。第一级空间配置器直接使用malloc()、realloc()、free()函数进行内存空间的分配和释放,而第二级空间配置器采用了内存池技术,通过空闲链表来管理内存。

    STL迭代器删除元素

    对于序列容器vector,deque来说,使用erase(itertor)后,后边的每个元素的迭代器都会失效,但是后边每个元素都会往前移动一个位置,但是erase会返回下一个有效的迭代器;

    对于关联容器map set来说,使用了erase(iterator)后,当前元素的迭代器失效,但是其结构是红黑树,删除当前元素的,不会影响到下一个元素的迭代器,所以在调用erase之前,记录下一个元素的迭代器即可(因为不会影响到下一个元素)

    对于list来说,它使用了不连续分配的内存,并且它的erase方法也会返回下一个有效的iterator,因此上面两种正确的方法都可以使用

    STL由什么基本组成(重新回顾下侯捷)

    容器,迭代器,仿函数,算法,分配器,配接器

    他们之间的关系:分配器给容器分配存储空间,算法通过迭代器获取容器中的内容,仿函数可以协助算法完成各种操作,配接器用来套接适配仿函数

    vector和list的区别:

    1)vector底层实现是数组;list是双向链表。

    2)vector支持随机访问,list不支持。

    3)vector是顺序内存,list不是。

    4)vector在中间节点进行插入删除会导致内存拷贝,list不会。

    5)vector一次性分配好内存,不够时才进行2倍扩容;list每次插入新节点都会进行内存申请。

    6)vector随机访问性能好,插入删除性能差;list随机访问性能差,插入删除性能好。

    STL中迭代器的作用,有指针为何还要迭代器

    Iterator模式是运用于聚合对象的一种模式,通过运用该模式,使得我们可以在不知道对象内部表示的情况下,按照一定顺序(由iterator提供的方法)访问聚合对象中的各个元素。

    STL中将容器与算法分开实现,容器负责数据的存储,算法代表着用系统的方法描述解决问题的策略机制。也就是说一个输入-处理-输出的流程,其中在处理过程中就需要对输入的数据能够进行读取或者修改等。而算法中的输入为某些容器时,算法可能就需要知道容器能够提供对其的访问函数。但是每个容器的访问函数都不一定相同,这时候如果针对每一个容器,算法都需要有特定的版本,这样会造成大量的代码冗余。那么怎么办呢?

    我们可以在容器与算法之间,用迭代器将其撮合在一起,算法通过迭代器来访问容器,而无需关心容器内的具体实现。通过设计一个抽象的迭代器接口定义一个统一的实现方式。由于每一个容器中的内部存储模式都不一样,因此对于每一个类别的容器都需要有一个专属迭代器来完成对数据的访问,该迭代器继承并实现于抽象的迭代器接口。

    迭代器和指针的区别

    迭代器不是指针,是类模板,表现的像指针。他只是模拟了指针的一些功能,通过重载了指针的一些操作符,->、*、++、--等。迭代器封装了指针,是一个“可遍历STL( Standard Template Library)容器内全部或部分元素”的对象, 本质是封装了原生指针,是指针概念的一种提升(lift),提供了比指针更高级的行为,相当于一种智能指针,他可以根据不同类型的数据结构来实现不同的++,--等操作。

    迭代器返回的是对象引用而不是对象的值,所以cout只能输出迭代器使用*取值后的值而不能直接输出其自身。

    STL迭代器是怎么删除元素的(迭代器失效)

    1.对于序列容器vector,deque来说,使用erase(itertor)后,后边的每个元素的迭代器都会失效,但是后边每个元素都会往前移动一个位置,但是erase会返回下一个有效的迭代器;
    2.对于关联容器map set来说,使用了erase(iterator)后,当前元素的迭代器失效,但是其结构是红黑树,删除当前元素的,不会影响到下一个元素的迭代器,所以在调用erase之前,记录下一个元素的迭代器即可。
    3.对于list来说,它使用了不连续分配的内存,并且它的erase方法也会返回下一个有效的iterator,因此上面两种正确的方法都可以使用。

    STL里resize和reserve的区别

    1. reserve()

    对于n值的大小,分两种情况:

    (1)如果n大于容器现有的容量(capacity),比如你容器原来是100的容量,我现在指定n=200,那么就需要在自由内存区为整个容器重新分配一块新的更大的连续空间【因为vector是顺序容器,所以存储空间是连续的,如果之前的存储空间不够了,必须这样做】,然后将容器内所有的有效元素从旧位置全部复制到新位置,这个过程是调用拷贝构造函数,然后释放旧位置的所有存储空间,并调整容器的元素位置指示器。所以reserve的时候如果n比原来的大,结果只是让容器的冗余容量(即没有分配元素的存储区)变大,容器的实际大小,即元素个数并没有改变。

    (2)如果n小于容器原来的容量,那么这个函数什么作用都没有。相当于白调用了(即容量不发生变化,还是原来的容量)。

    2. resize()

    其中n是要保留的元素个数,如果是要新增元素的话,c则是新增元素的默认初始值。

    对于n值的大小,分三种情况:

    (1)如果n大于容器当前的大小(即容器的size,这里和capacity无关),则在容器的末尾插入n-size()个初始值为c的元素;如果没有指定初始值,那就元素类型的默认构造函数来初始化。

    (2)如果n小于容器当前的大小,则删除末尾的size()-n个元素,这样就导致容器的大小变了,size 变小了。但是这种类型的容器在删除一个元素的时候并不会释放元素本身的内存空间【这也是为了保留这块空间以避免将来要插入新元素的时候又要进行存储空间重分配】,所以容器的容量即capacity其实是没有改变的

    (3)n等于容器当前的大小,则什么也不做。

  • 相关阅读:
    【BZOJ2806】【CTSC2012】—熟悉的文章(二分答案+广义后缀自动机+单调队列优化dp)
    2017-2-15
    2017-2-14
    2017-2-13
    CSS居中
    2017-2-10
    微信小程序
    2017-2-9
    2017-2-8
    基础知识再整理: 01
  • 原文地址:https://www.cnblogs.com/lxy-xf/p/11335568.html
Copyright © 2011-2022 走看看