C++----STL

STL基本概念

         STL = Standard Template Library,标准模板库,它是一个容器模板、迭代器模板、函数对象模板和算法模板的集合。它们的设计都是基于泛型编程原则的。STL容器是一个与数组类似的单元,可以存储若干个值;算法是完成特定任务的处方,算法通过使用模板,从而独立于所存储的对象的类型;通过使用迭代器接口,从而独立于容器的类型。迭代器是广义指针。

容器

1.1容器类型是可用于创建具体容器对象的模板。

1.2、STL的容器可以分为以下几个大类:
     (1)序列容器: 有vector、list、 deque、string、forward_list、array(也被归为序列容器,虽然并不满足所有要求)。

     (2)关联容器:   有set、 multiset、 map、 mulmap、hash_set、 hash_map、hash_multiset、 hash_multimap。(对容器概念的改进,将值与键关联在一起,并使用键来查找值。

       (3)容器配接器:Stack、Queue、Priority Queue

1.3STL各个容器的实现:

     (1)、Vector

          头文件:#inlcude

         内部数据结构:数组。

       特点:

       ① 随机访问每个元素,所需要的时间为常量。

       ② 在末尾增加或删除元素所需时间与元素数目无关,在中间或开头增加或删除元素所需时间随元素数目呈线性变化。

       ③ 可动态增加或减少元素,内存管理自动完成,但程序员可以使用reserve()成员函数来管理内存。

       ④ vector的迭代器在内存重新分配时将失效(它所指向的元素在该操作的前后不再相同)。当把超过capacity()-size()个元素插入vector中时,内存会重新分配,所有的迭代器都将失效;否则,指向当前元素以后的任何元素的迭代器都将失效。当删除元素时,指向被删除元素以后的任何元素的迭代器都将失效。

      常用函数:

c.assign(beg,end) c.assign(n,elem)                 //将(beg; end)区间中的数据赋值给c。将n个elem的拷贝赋值给c。
c.at(idx)                                         //传回索引idx所指的数据,如果idx越界,抛出out_of_range。
c.back()                                           //传回最后一个数据,不检查这个数据是否存在。
c.begin()                                          //传回迭代器中的第一个数据地址。
c.capacity()                                       //返回容器中数据个数。
c.clear()                                          //移除容器中所有数据。
c.empty()                                          //判断容器是否为空。
c.end()                                             //指向迭代器中末端元素的下一个,指向一个不存在元素。
c.erase(pos)                                        //删除pos位置的数据,传回下一个数据的位置。
c.erase(beg,end)                                   //删除[beg,end)区间的数据,传回下一个数据的位置。
c.front()                                         //传回第一个数据。
get_allocator                                      //使用构造函数返回一个拷贝。
c.insert(pos,elem)                                  //在pos位置插入一个elem拷贝,传回新数据位置
c.insert(pos,n,elem)                                //在pos位置插入n个elem数据,无返回值
c.insert(pos,beg,end)                               //在pos位置插入在[beg,end)区间的数据。无返回值
c.max_size()                                       //返回容器中最大数据的数量。
c.pop_back()                                       //删除最后一个数据。
c.pop_front()                                       //删除头部数据。
c.push_back(elem)                                  //在尾部加入一个数据。
c.rbegin()                                         //传回一个逆向队列的第一个数据。
c.rend()                                           //传回一个逆向队列的最后一个数据的下一个位置。
c.resize(num)                                     //重新指定队列的长度。
c.reserve()                                        //保留适当的容量。
c.size()                                           //返回容器中实际数据的个数。
c1.swap(c2)                                         //将c1和c2元素互换

   (2)、Deque

      头文件:#include         

      内部数据结构:双端队列

      特点:

      随机访问每个元素,所需要的时间为常量。

      在开头和末尾增加元素所需时间与元素数目无关,在中间增加或删除元素所需时间随元素数目呈线性变化。

      可动态增加或减少元素,内存管理自动完成,不提供用于内存管理的成员函数。

      增加任何元素都将使deque的迭代器失效。在deque的中间删除元素将使迭代器失效。在deque的头或尾删除元素时,只有指向该元素的迭代器失效。

        常用函数:与Vector相同

    (3)、List

      头文件:#include         

      内部数据结构:双向环状链表

      特点:

      不能随机访问一个元素

      可双向遍历

      ③在开头、末尾和中间任何地方增加或删除元素所需时间都为常量

      ④可动态增加或减少元素,内存管理自动完成

      ⑤增加任何元素都不会使迭代器失效。删除元素时,除了指向当前被删除元素的迭代器外,其它迭代器都不会失效。

         常用函数:与Vector相同

   (4)、Slist

      头文件:#include         

      内部数据结构:单向链表

      特点:

      不可双向遍历,只能从前到后地遍历

      其它的特性同list相似。

         常用函数:

 * void swap(slist&);
 * iterator insert_after(iterator pos,const T& x);  // 注意与前面不同的是,这里是在POS位置之后进行插入
 *                                                  // vector、deque、list都是POS前插入
 * iterator insert(iterator pos,const T& X);        // 找到pos的前驱,再调用insert_after进行插入(pos前插入)
 * void pop_front();
 * iterator erase(iterator pos);
 * iterator erase(iterator first,iterator last);    // 注意是半闭区间[first,last)
 * void clear();
 * void remove(const T& x);                         // 删除所有等于value的元素
 * void splice(iterator pos,slist& x);              //将源list的内容部分或全部元素删除,拼插入到目的list。
 * void splice(iterator pos,iterator i);
 * void merge(slist& x);                            //合并链表
 * void sort();                                     // 按"<"关系进行排序
 * void unique();                                   // 删除重复元素,仅保留一个

     (5)、Stack

    头文件:#inlcude

         内部数据结构:它可以将任意类型的序列容器转换为一个堆栈,一般使用deque作为支持的序列容器。

      特点:

      ①元素只能后进先出(LIFO)。

      ②不能遍历整个stack。

         常用函数:

 bool empty()const;
 size_type size();
 T &pop();
 void push(const T &x);
 void pop();

     (6)、Queue

         头文件:#inlcude

        内部数据结构:它可以将任意类型的序列容器转换为一个队列,一般使用deque作为支持的序列容器。

         特点:

         元素只能先进先出(FIFO)。

      ②不能遍历整个queue。

         常用函数:

 bool empty()const;
 size_type size();
 T &front();
 T &back();
 void push(const T &x);
 void pop();

     (7)Priority_Queue

         头文件:#inlcude

        内部数据结构:它可以将任意类型的序列容器转换为一个优先队列,一般使用vector作为底层存储结构.

      特点:

      适配器,它可以将任意类型的序列容器转换为一个优先级队列,一般使用vector作为底层存储方式。

      只能访问第一个元素,不能遍历整个priority_queue。

      第一个元素始终是优先级最高的一个元素。

     (8)Set

         头文件:#inlcude

        内部数据结构:二叉树

      特点:

      键和值相等。

      键唯一。

      元素默认按升序排列。

        如果迭代器所指向的元素被删除,则该迭代器失效。其它任何增加、删除元素的操作都不会使迭代器失效。

     (9)Multiset

         头文件:#inlcude

        内部数据结构:二叉树

      特点:

      键可以不唯一。

      其它特点与set相同。

    (10)Map

         头文件:#inlcude

        内部数据结构:二叉树。

      特点:

      键唯一。

      元素默认按键的升序排列。

        如果迭代器所指向的元素被删除,则该迭代器失效。其它任何增加、删除元素的操作都不会使迭代器失效。

    (11)Multimap

         头文件:#inlcude

        内部数据结构:二叉树

      特点:

      键可以不唯一。

      其它特点与map相同。

         注意:关联容器支持通过键来高效地查找和读取元素,两个基本的关联容器是map和set。map的元素是“键-值”对的二元组形式:键用作元素在map中的索引,而值则表示所存储和读取的数据。set仅包含一个键,并有效地支持关于某个键是否存在的查询。set和map类型的对象所包含的元素都具有不同的键。如果需要一个键对应多个实例,则需要使用multimap或multiset类型。这两种类型允许多个元素拥有相同的键。

    (12)Hash_Set

         头文件:#inlcude

        内部数据结构:哈希表。

      特点:

       与set相比较,它里面的元素不一定是经过排序的,而是按照所用的hash函数分派的,它能提供更快的搜索速度(当然跟hash函数有关)。

      其它特点与set相同。

    (13)Hash_Multiset

         头文件:#inlcude

        内部数据结构:哈希表。

      特点:

      键可以不唯一。

      其它特点与hash_set相同。

   (14)Hash_Map

         头文件:#inlcude

        内部数据结构:哈希表。

      特点:

      与map相比较,它里面的元素不一定是按键值排序的,而是按照所用的hash函数分派的,它能提供更快的搜索速度(当然也跟hash函数有关)。

      其它特点与map相同。

   (15)Hash_Multimap

      头文件:#inlcude <hash_map>

        内部数据结构:哈希表。

      特点:

      键可以不唯一。

      其它特点与hash_map相同。

         注意:带有hash字样的关联容器,内部结构是哈希表,其它特性不变。hashtable 可以提供任何有名项的存取操作和删除操作,由于操作对象是有名项,故可被视为一种字典结构。用意是在常数时间内提供基本操作。常见的,我们可以把int存到相应值的数组里面,就可以通过O(1)的时间存取和删除。主要思想是通过hash函数,把对象映射到一个较小的容器里面,并且保证时间复杂度。映射到较小容器很可能出现碰撞问题,解决的方法常见的有:线性探测,二次探测,开链法。STL利用vector来当容器,采用开链法来解决冲突,从而实现hashtable。hashtable只能处理char,int,short等类型,不能处理string,double,float类型,想要处理的话必须自己加hash function.

迭代器

2.1、基本概念

         迭代器(iterator)是连接容器和算法的纽带,为数据提供了抽象,使写算法的人不必关心各种数据结构的细节。迭代器提供了数据访问的标准模型——对象序列,使对容器更广泛的访问操作成为可能。

         泛型编程的关键所在,就是如何找到一种通用的方法,来访问具有不同结构的各种容器中的每个元素,而这正是迭代器的功能。

         迭代器是一种广义的指针,是指向序列元素指针概念的一种抽象。迭代器可以指向容器中的任意元素,还能遍历整个容器。

https://p-blog.csdn.net/images/p_blog_csdn_net/touzani/303255/o_iterater.jpg

       (序列)容器是数组的抽象,而迭代器则是指向数组指针的抽象。迭代器虽然是广义的指针,但是,迭代器并不是通用的指针。不同的容器可能需要不同的迭代器,实际上,STL中,为每种容器都typedef了一个迭代器,名为iterator。例如,vector的迭代器类型为::iterator(是一种随机访问迭代器)、list的迭代器类型为list::iterator(是一种双向迭代器)。

2.2、类型:

       (1) 输入迭代器(input iterator)——用于读取容器中的信息,但不一定能够修改它。

                     输入迭代器iter通过解除引用(即*iter),来读取容器中其所指向元素之值;

                   为了使输入迭代器能够访问容器中的所有元素的值,必须使其支持(前/后缀格式的)++ 操作符;

                     输入迭代器不能保证第二次遍历容器时,顺序不变;也不能保证其递增后,先前指向的值不变。即,基于输入迭代器的任何算法,都应该是单通(single-pass)的,不依赖于前一次遍历时的值,也不依赖于本次遍历中前面的值。

                   可见输入迭代器是一种单向的只读迭代器,可以递增但是不能递减,而且只能读不能写。适用于单通只读型算法。

       (2) 输出迭代器(output iterator)——用于将信息传输给容器(修改容器中元素的值),但是不能读取。例如,显示器就是只能写不能读的设备,可用输出容器来表示它。也支持解除引用和++操作,也是单通的。所以,输出迭代器适用于单通只写型算法。

       (3)前向迭代器(forward iterator正向迭代器)——只能使用++操作符来单向遍历容器(不能用--)。与I/O迭代器一样,前向迭代器也支持解除引用与++操作。与I/O迭代器不同的是,前向迭代器是多通的(multi-pass)。即,它总是以同样的顺序来遍历容器,而且迭代器递增后,仍然可以通过解除保存的迭代器引用,来获得同样的值。另外,前向迭代器既可以是读写型的,也可以是只读的。

       (4)双向迭代器(bidirectional iterator)——可以用++和--操作符来双向遍历容器。其他与前向迭代器一样,也支持解除引用、也是多通的、也是可读写或只读的。

       (5)随机访问迭代器(random access iterator)——可直接访问容器中的任意一个元素的双向迭代器。

可见,这5种迭代器形成了一个层次结构:I/O迭代器(都可++遍历,但是前者只读/后者只写)最基本、前向迭代器可读写但只能++遍历、双向迭代器也可读写但能++/--双向遍历、随机迭代器除了能够双向遍历外还能够随机访问。

 

https://p-blog.csdn.net/images/p_blog_csdn_net/touzani/303255/o_iter.jpg

算法

3.1    STL算法部分主要由头文件,,组成。要使用 STL中的算法函数必须包含头文件,对于数值算法须包含中则定义了一些模板类,用来声明函数对象。

编译器无法检测出所传递的迭代器是一个无效形式的迭代器,当然也无法给出算法函数错误的提示,因为迭代器并不是真实的类别,它只是传递给函数模板的一种参数格式而已。

3.2   STL中算法分类:

  • 操作对象
    • 直接改变容器的内容
    • 将原容器的内容复制一份,修改其副本,然后传回该副本
  • 功能:
    • 非可变序列算法 指不直接修改其所操作的容器内容的算法
    • 可变序列算法 指可以修改它们所操作的容器内容的算法
    • 排序算法 包括对序列进行排序和合并的算法、搜索算法以及有序序列上的集合操作
    • 数值算法 对容器内容进行数值计算

修改性序列操作(27个)

复制

copy()

从序列的第一个元素起进行复制

copy_backward()

从序列的最后一个元素起进行复制

交换

swap()

交换两个元素

swap_ranges()

交换指定范围的元素

iter_swap()

交换由迭代器所指的两个元素

变换

transform()

将某操作应用于指定范围的每个元素

替换

replace()

用一个给定值替换一些值

replace_if()

替换满足谓词的一些元素

replace_copy()

复制序列时用一给定值替换元素

replace_copy_if()

复制序列时替换满足谓词的元素

填充

fill()

用一给定值取代所有元素

fill_n()

用一给定值取代前n个元素

生成

generate()

用一操作的结果取代所有元素

generate_n()

用一操作的结果取代前n个元素

删除

remove()

删除具有给定值的元素

remove_if()

删除满足谓词的元素

remove_copy()

复制序列时删除具有给定值的元素

remove_copy_if()

复制序列时删除满足谓词的元素

唯一

unique()

删除相邻的重复元素

unique_copy()

复制序列时删除相邻的重复元素

反转

reverse()

反转元素的次序

reverse_copy()

复制序列时反转元素的次序

环移

rotate()

循环移动元素

rotate_copy()

复制序列时循环移动元素

随机

random_shuffle()

采用均匀分布来随机移动元素

划分

partition()

将满足某谓词的元素都放到前面

stable_partition()

将满足某谓词的元素都放到前面并维持原顺序

 

序列排序及相关操作(27个)

排序

sort()

以很好的平均效率排序

stable_sort()

排序,并维持相同元素的原有顺序

partial_sort()

将序列的前一部分排好序

partial_sort_copy()

复制的同时将序列的前一部分排好序

第n个元素

nth_element()

将第n各元素放到它的正确位置

二分检索

lower_bound()

找到大于等于某值的第一次出现

upper_bound()

找到大于某值的第一次出现

equal_range()

找到(在不破坏顺序的前提下)可插入给定值的最大范围

binary_search()

在有序序列中确定给定元素是否存在

归并

merge()

归并两个有序序列

inplace_merge()

归并两个接续的有序序列

有序结构上的集合操作

includes()

一序列为另一序列的子序列时为真

set_union()

构造两个集合的有序并集

set_intersection()

构造两个集合的有序交集

set_difference()

构造两个集合的有序差集

set_symmetric_difference()

构造两个集合的有序对称差集(并-交)

堆操作

push_heap()

向堆中加入元素

pop_heap()

从堆中弹出元素

make_heap()

从序列构造堆

sort_heap()

给堆排序

最大和最小

min()

两个值中较小的

max()

两个值中较大的

min_element()

序列中的最小元素

max_element()

序列中的最大元素

词典比较

lexicographical_compare()

两个序列按字典序的第一个在前

排列生成器

next_permutation()

按字典序的下一个排列

prev_permutation()

按字典序的前一个排列

make_heap(c.begin(),c.end());            //默认建立一个堆
push_heap(c.begin(),c.end())            //新添加一个元素在末尾,然后重新调整堆序。也就是把元素添加在底层vector的end()处。
pop_heap(c.begin(),c.end());            //把堆顶元素取出来,放到了数组或者是vector的末尾,用原来末尾元素去替代
sort_heap(c.begin(),c.end());           //持续对整个heap做pop_heap操作




你可能感兴趣的:(C/C++,C++,c++,迭代器,容器)