C++容器、迭代器07

        --------------------------------------------------------------------

1、根据给定的函数声明,实现函数功能,即在参数str所指向的字符串中搜索第一次出现字符c的位置。

char *func(const char *str, int c)

/*
    func   :    从给定字符串str中找到第一次匹配字符c的位置,并返回该指向的地址
    str    :    给定字符串
    c      :    要匹配的字符
    return :   成功,返回该位置的地址
                失败,返回空地址
*/
char *func(const char *str, int c)
{
    int i = 0;
    
    for (i = 0; str[i] != '\0'; i++)
        if (str[i] == c)
            return &str[i];
    return NULL;
}

 2、完成有头单项不循环链表的创建头节点以及插入数据节点(头插法 尾插法),自己定义结构体。

<llist.h>

#ifndef __LLIST_H__
#define __LLIST_H__

typedef struct ListNode {
    struct ListNode *next;
    char data[1];    
}LNode;

typedef struct {
    LNode head;
    size_t size;     // 数据节点节点域的大小
}List;

List *list_init(List **list, const size_t dataSize);

int list_head_insert(List *list, const void *data);

int list_tail_insert(List *list, const void *data);

#endif

<llist.c>

#include "llist.h"
#include <stdlib.h>
#include <string.h>

int list_init(List **list, const size_t dataSize)
{

    *list= malloc(sizeof(List));
    if (!*list) return -1;

    (*list)->head.next = NULL;
    (*list)->size = dataSize;   
    
    return 0;
}

static int __node_init(LNode **node, cosnt void *data, int size)
{
    *node = malloc(sizeof(LNode) + size);
    if (!*node) return -1;

    (*node)->next = NULL;
    memcpy(node->data, data, size);

    return 0;
}

int list_head_insert(List *list, const void *data)
{
    LNode *newnode = NULL;

    if (-1 == __node_init(&newnode, data, list->size)) 
        return -1;

    newnode->next = list->head.next;
    list->head.next = newnode;

    return 0;
}

int list_tail_insert(List *list, const void *data)
{
    LNode *newnode = NULL;
    LNode *cur = list->head;

    if (-1 == __node_init(&newnode, data, list->size)) 
        return -1;

    if (!cur->next) {
        list->head.next = newnode;
    } else {
        while (cur->next)
            cur = cur->next;
        cur->next = newnode;
    }

    return 0;
}

--------------------------------------------------------------------

 一、STL

        1、简介

                STL就是标准模板库的意思(Standard Template Library)

                STL的代码从广义上来讲分为三类:

                        【1】algorithm(算法):为容器提供了大量的操作,例如:排序\查找、、、

                        【2】container(容器):用来存储管理大量的数据,其实就是数据结构

                        【3】iterator(迭代器):架起容器和算法的桥梁,将容器与算法结合到一起

                STL标准模板库的实现就是采用了模板类和模板函数的方式,使其更加通用。

        2、手册

<array>数组(实例化时指定长度)

<deque>

(double-ended queue)

双端队列
<forward_list>单链表
<list>双链表
<map>类似于字典,处理一对一有关联的数组
<queue>队列
<set>集合,树结构
<stack>
<unordered_map>无序的map
<unordered_set>无序的set
<vector>向量(可变长的数组)

        3、容器(Containers)

                1)分类

                        序列容器(线性)

                        array、vector、deque、forward_list、list

                        容器适配器

                        stack、queue

                        关联容器

                        set、map、pair、multiset、multimap

                        无序关联容器

                        unordered_set、unordered_map

                2)array(数组)

/*

        T:所包含元素的类型,别名为成员的类型:array::valur_type

        N:数组的大小,成员的个数

        other:

                array类是一个固定大小的序列容器,需要在初始化时,严格指定成员个数

*/

 template < class T, size_t N > class array;

/*

        ps:C++标准库新增加了begin()和end()这两个函数,与array容器包含的成员函数不同的是,标准库提供的这两个函数的操作对象,既可以是容器,也可以是普通数组。当操作对象是容器时,它和容器包含的成员函数的功能完全相同;如果操作对象是普通数组,则begin()函数返回的是数组第一个元素的指针,end()函数返回的是指向数组中最后一个元素之后一个位置的指针。

                在array头文件中,重载了get()全局函数,它可以访问容器中指定的元素,并返回该元素的引用。

                get<pos>(values)

*/

成员函数功能
begin()返回指向容器中第一个元素的随机访问迭代器。
end()返回指向容器最后一个元素之后一个位置的随机访问迭代器,通常和 begin() 结合使用。
rbegin()返回指向最后一个元素的随机访问迭代器。
rend()返回指向第一个元素之前一个位置的随机访问迭代器。
cbegin()和 begin() 功能相同,只不过在其基础上增加了 const 属性,不能用于修改元素。
cend()和 end() 功能相同,只不过在其基础上,增加了 const 属性,不能用于修改元素。
crbegin()和 rbegin() 功能相同,只不过在其基础上,增加了 const 属性,不能用于修改元素。
crend()和 rend() 功能相同,只不过在其基础上,增加了 const 属性,不能用于修改元素。
size()返回容器中当前元素的数量,其值始终等于初始化 array 类的第二个模板参数 N。
max_size()返回容器可容纳元素的最大数量,其值始终等于初始化 array 类的第二个模板参数 N。
empty()判断容器是否为空,和通过 size()==0 的判断条件功能相同,但其效率可能更快。
at(n)返回容器中 n 位置处元素的引用,该函数自动检查 n 是否在有效的范围内,如果不是则抛出 out_of_range 异常。
front()返回容器中第一个元素的直接引用,该函数不适用于空的 array 容器。
back()返回容器中最后一个元素的直接应用,该函数同样不适用于空的 array 容器。
data()返回一个指向容器首个元素的指针。利用该指针,可实现复制容器中所有元素等类似功能。
fill(val)将 val 这个值赋值给容器中的每个元素。
array1.swap(array2)交换 array1 和 array2 容器中的所有元素,但前提是它们具有相同的长度和类型。
                3)forward_list(单链表)

/*

        T:所包含元素的类型,别名为成员的类型:array::valur_type

        Alloc:指定分配器对象的类型

*/
template < class T, class Alloc = allocator<T> > class forward_list;

/*

        ps:C++标准库新增加了begin()和end()这两个函数,与forward_list容器包含的成员函数不同的是,标准库提供的这两个函数的操作对象,既可以是容器,也可以是普通数组。当操作对象是容器时,它和容器包含的成员函数的功能完全相同;如果操作对象是普通数组,则begin()函数返回的是数组第一个元素的指针,end()函数返回的是指向数组中最后一个元素之后一个位置的指针。

                在forward_list头文件中,有一个std::swap(x,y)非成员函数(其中x和y是存储相同类型的forward_list容器),它与swap()成员函数的功能完全相同

                swap(x,y)

*/

成员函数功能
before_begin()返回一个前向迭代器,其指向容器中第一个元素之前的位置。
begin()返回一个前向迭代器,其指向容器中第一个元素的位置。
end()返回一个前向迭代器,其指向容器中最后一个元素之后的位置。
cbefore_begin()和 before_begin() 功能相同,只不过在其基础上,增加了 const 属性,不能用于修改元素。
cbegin()和 begin() 功能相同,只不过在其基础上,增加了 const 属性,不能用于修改元素。
cend()和 end() 功能相同,只不过在其基础上,增加了 const 属性,不能用于修改元素。
empty()判断容器中是否有元素,若无元素,则返回 true;反之,返回 false。
max_size()返回容器所能包含元素个数的最大值。这通常是一个很大的值,一般是 232-1,所以我们很少会用到这个函数。
front()返回第一个元素的引用。
assign()用新元素替换容器中原有内容。
push_front()在容器头部插入一个元素。
emplace_front()在容器头部生成一个元素。该函数和 push_front() 的功能相同,但效率更高。
pop_front()删除容器头部的一个元素。
emplace_after()在指定位置之后插入一个新元素,并返回一个指向新元素的迭代器。和 insert_after() 的功能相同,但效率更高。
insert_after()在指定位置之后插入一个新元素,并返回一个指向新元素的迭代器。
erase_after()删除容器中某个指定位置或区域内的所有元素。
swap()交换两个容器中的元素,必须保证这两个容器中存储的元素类型是相同的。
resize()调整容器的大小。
clear()删除容器存储的所有元素。
splice_after()将某个 forward_list 容器中指定位置或区域内的元素插入到另一个容器的指定位置之后。
remove(val)删除容器中所有等于 val 的元素。
remove_if()删除容器中满足条件的元素。
unique()删除容器中相邻的重复元素,只保留一个。
merge()合并两个事先已排好序的 forward_list 容器,并且合并之后的 forward_list 容器依然是有序的。
sort()通过更改容器中元素的位置,将它们进行排序。(默认升序排列,可以通过传递自定义的比较方法或仿函数类,按照该方法进行排序)
reverse()反转容器中元素的顺序。

-------------------------------------------------------------------------

仿函数:

        其实就是一个类的使用,看上去像一个函数调用,其实就是类中实现一个函数调用运算符的重载:operator()

        class MyCmp {

                public :

                        bool operator()(const int &lhs, const int &rhs) const {return lhs < rhs;}

        };

------------------------------------------------------------------------- 

                4) list(双链表)

/*

        T:所包含元素的类型,别名为成员的类型:array::valur_type

        Alloc:指定分配器对象的类型

*/

template < class T, class Alloc = allocator<T> > class list;

/*

        ps:C++标准库新增加了begin()和end()这两个函数,与list容器包含的成员函数不同的是,标准库提供的这两个函数的操作对象,既可以是容器,也可以是普通数组。当操作对象是容器时,它和容器包含的成员函数的功能完全相同;如果操作对象是普通数组,则begin()函数返回的是数组第一个元素的指针,end()函数返回的是指向数组中最后一个元素之后一个位置的指针。

                在list头文件中,有一个std::swap(x,y)非成员函数(其中x和y是存储相同类型的ist容器),它与swap()成员函数的功能完全相同

                swap(x,y)

*/

成员函数功能
begin()返回指向容器中第一个元素的双向迭代器。
end()返回指向容器中最后一个元素所在位置的下一个位置的双向迭代器。
rbegin()返回指向最后一个元素的反向双向迭代器。
rend()返回指向第一个元素所在位置前一个位置的反向双向迭代器。
cbegin()和 begin() 功能相同,只不过在其基础上,增加了 const 属性,不能用于修改元素。
cend()和 end() 功能相同,只不过在其基础上,增加了 const 属性,不能用于修改元素。
crbegin() 和 rbegin() 功能相同,只不过在其基础上,增加了 const 属性,不能用于修改元素。
crend()和 rend() 功能相同,只不过在其基础上,增加了 const 属性,不能用于修改元素。
empty()判断容器中是否有元素,若无元素,则返回 true;反之,返回 false。
size()返回当前容器实际包含的元素个数。
max_size()返回容器所能包含元素个数的最大值。这通常是一个很大的值,一般是 232-1,所以我们很少会用到这个函数。
front()返回第一个元素的引用。
back()返回最后一个元素的引用。
assign()用新元素替换容器中原有内容。
emplace_front()在容器头部生成一个元素。该函数和 push_front() 的功能相同,但效率更高。
push_front()在容器头部插入一个元素。
pop_front()删除容器头部的一个元素。
emplace_back()在容器尾部直接生成一个元素。该函数和 push_back() 的功能相同,但效率更高。
push_back()在容器尾部插入一个元素。
pop_back()删除容器尾部的一个元素。
emplace()在容器中的指定位置插入元素。该函数和 insert() 功能相同,但效率更高。
insert() 在容器中的指定位置插入元素。
erase()删除容器中一个或某区域内的元素。
swap()交换两个容器中的元素,必须保证这两个容器中存储的元素类型是相同的。
resize()调整容器的大小。
clear()删除容器存储的所有元素。
splice()将一个 list 容器中的元素插入到另一个容器的指定位置。
remove(val)删除容器中所有等于 val 的元素。
remove_if()删除容器中满足条件的元素。
unique()删除容器中相邻的重复元素,只保留一个。
merge()合并两个事先已排好序的 list 容器,并且合并之后的 list 容器依然是有序的。
sort()通过更改容器中元素的位置,将它们进行排序。(默认升序排列,可以通过传递自定义的比较方法或仿函数类,按照该方法进行排序)
reverse()反转容器中元素的顺序。
                5)pair---(适配键值对的类,将两个对象视为单个对象)        

/*

        T1:第一个对象的类型

        T2:第二个对象的类型

*/

template <class T1, class T2> struct pair;

/*
        ps:pair将一对值(T1和T2)组合为一个值,这一对值可以具有不同的数据类型,

                T1使用pair的公有函数first访问

                T2使用pair的公有函数second访问

*/

创建与初始化 (必须提供两个类型名,可以不相同)

        pair<string, string> p1;           // 创建一个空对象p1,两个元素类型都是string
        pair<string, int> p2;                // 创建一个空对象 p2, 两个元素类型分别是string和int类型
        pair<string, vector<int>> p3;  // 创建一个空对象p3,两个元素类型分别是string和vector类型

        pair<string, string> author("au1","au2");    // 创建一个author对象,两个元素类型分别为string类型,并默认初始值为au1和au2。
        pair<string, int> boy("Tom", 18);                // 创建一个boy对象,两个元素类型分别为string类型,并默认初始值为"Tom"和18。
        pair<string, int> boy2(boy);                       // 拷贝构造初始化

 pair对象操作(通过first和second访问)

        pair<int, string> p1;

        p1.first = 1;

        p1.second = "zxb";

        cout << p1.first << " is " << p1.second << endl;

// 输出结果:1 is zxb

生成新的pair对象(make_pair)

        pair<int, string> p1;

        p1 = make_pair(1, "zxb");

        cout << p1.first << " is " << p1.second << endl;

// 输出结果:1 is zxb 

 将pair对象作为返回值并获取元素值(tie)

        pair<string, int> getPreson() {
            return make_pair("zxb", 3);
        }
 
        int main(int argc, char **argv) {
                string name;
                int ages;
                tie(name, ages) = getPreson();
                cout << "name: " << name << ", ages: " << ages << endl;
                return 0;
        }

// 输出结果:name:zxb,ages:3        

                6)set (集合)

/*

        T:所包含元素的类型,别名为成员的类型:array::valur_type

        Compare:指定set容器内部的排序规则(默认升序)

        Alloc:指定分配器对象的类型

*/

template < class T,                                         // set::key_type/value_type
                   class Compare = less<T>,          // set::key_compare/value_compare         

                   class Alloc = allocator<T>          // set::allocator_type
                > class set;

/*
        ps:使用set容器存储的各个键值对,要求键key值和value值必须相等,并且使用set容器存储的各个元素的值必须各不相同。

*/

成员函数功能
begin()返回指向容器中第一个(注意,是已排好序的第一个)元素的双向迭代器。如果 set 容器用 const 限定,则该方法返回的是 const 类型的双向迭代器。
end()返回指向容器最后一个元素(注意,是已排好序的最后一个)所在位置后一个位置的双向迭代器,通常和 begin() 结合使用。如果 set 容器用 const 限定,则该方法返回的是 const 类型的双向迭代器。
rbegin()返回指向最后一个(注意,是已排好序的最后一个)元素的反向双向迭代器。如果 set 容器用 const 限定,则该方法返回的是 const 类型的反向双向迭代器。
rend()返回指向第一个(注意,是已排好序的第一个)元素所在位置前一个位置的反向双向迭代器。如果 set 容器用 const 限定,则该方法返回的是 const 类型的反向双向迭代器。
cbegin()和 begin() 功能相同,只不过在其基础上,增加了 const 属性,不能用于修改容器内存储的元素值。
cend()和 end() 功能相同,只不过在其基础上,增加了 const 属性,不能用于修改容器内存储的元素值。
crbegin()和 rbegin() 功能相同,只不过在其基础上,增加了 const 属性,不能用于修改容器内存储的元素值。
crend()和 rend() 功能相同,只不过在其基础上,增加了 const 属性,不能用于修改容器内存储的元素值。
find(val)在 set 容器中查找值为 val 的元素,如果成功找到,则返回指向该元素的双向迭代器;反之,则返回和 end() 方法一样的迭代器。另外,如果 set 容器用 const 限定,则该方法返回的是 const 类型的双向迭代器。
lower_bound(val)返回一个指向当前 set 容器中第一个大于或等于 val 的元素的双向迭代器。如果 set 容器用 const 限定,则该方法返回的是 const 类型的双向迭代器。
upper_bound(val)返回一个指向当前 set 容器中第一个大于 val 的元素的迭代器。如果 set 容器用 const 限定,则该方法返回的是 const 类型的双向迭代器。
equal_range(val)该方法返回一个 pair 对象(包含 2 个双向迭代器),其中 pair.first 和 lower_bound() 方法的返回值等价,pair.second 和 upper_bound() 方法的返回值等价。也就是说,该方法将返回一个范围,该范围中包含的值为 val 的元素(set 容器中各个元素是唯一的,因此该范围最多包含一个元素)。
empty()若容器为空,则返回 true;否则 false。
size()返回当前 set 容器中存有元素的个数。
max_size()返回 set 容器所能容纳元素的最大个数,不同的操作系统,其返回值亦不相同。
insert()向 set 容器中插入元素。
erase()删除 set 容器中存储的元素。
swap()交换 2 个 set 容器中存储的所有元素。这意味着,操作的 2 个 set 容器的类型必须相同。
clear()清空 set 容器中所有的元素,即令 set 容器的 size() 为 0。
emplace()在当前 set 容器中的指定位置直接构造新元素。其效果和 insert() 一样,但效率更高。
emplace_hint()在本质上和 emplace() 在 set 容器中构造新元素的方式是一样的,不同之处在于,使用者必须为该方法提供一个指示新元素生成位置的迭代器,并作为该方法的第一个参数。
count(val)在当前 set 容器中,查找值为 val 的元素的个数,并返回。注意,由于 set 容器中各元素的值是唯一的,因此该函数的返回值最大为 1。
                7)map (映射)

/*

        Key:指定键(key)的类型

        T:指定值(value)的类型

        Compare:指定排序规则(根据键值的大小默认升序)

        Alloc:指定分配器对象的类型

*/

template < class Key,                                                          // map::key_type

                   class T,                                                              // map::mapped_type

                   class Compare = less<Key>,                          // map::key_compare

                   class Alloc = allocator<pair<const Key,T> > // map::allocator_type

                > class map;


/*
        ps:map存储的都是pair对象,但键的值不能重复且不能被修改

*/

成员函数功能
begin()返回指向容器中第一个(注意,是已排好序的第一个)键值对的双向迭代器。如果 map 容器用 const 限定,则该方法返回的是 const 类型的双向迭代器。
end()返回指向容器最后一个元素(注意,是已排好序的最后一个)所在位置后一个位置的双向迭代器,通常和 begin() 结合使用。如果 map 容器用 const 限定,则该方法返回的是 const 类型的双向迭代器。
rbegin()返回指向最后一个(注意,是已排好序的最后一个)元素的反向双向迭代器。如果 map 容器用 const 限定,则该方法返回的是 const 类型的反向双向迭代器。
rend()返回指向第一个(注意,是已排好序的第一个)元素所在位置前一个位置的反向双向迭代器。如果 map 容器用 const 限定,则该方法返回的是 const 类型的反向双向迭代器。
cbegin()和 begin() 功能相同,只不过在其基础上,增加了 const 属性,不能用于修改容器内存储的键值对。
cend()和 end() 功能相同,只不过在其基础上,增加了 const 属性,不能用于修改容器内存储的键值对。
crbegin()和 rbegin() 功能相同,只不过在其基础上,增加了 const 属性,不能用于修改容器内存储的键值对。
crend()和 rend() 功能相同,只不过在其基础上,增加了 const 属性,不能用于修改容器内存储的键值对。
find(key)在 map 容器中查找键为 key 的键值对,如果成功找到,则返回指向该键值对的双向迭代器;反之,则返回和 end() 方法一样的迭代器。另外,如果 map 容器用 const 限定,则该方法返回的是 const 类型的双向迭代器。
lower_bound(key)返回一个指向当前 map 容器中第一个大于或等于 key 的键值对的双向迭代器。如果 map 容器用 const 限定,则该方法返回的是 const 类型的双向迭代器。
upper_bound(key)返回一个指向当前 map 容器中第一个大于 key 的键值对的迭代器。如果 map 容器用 const 限定,则该方法返回的是 const 类型的双向迭代器。
equal_range(key)该方法返回一个 pair 对象(包含 2 个双向迭代器),其中 pair.first 和 lower_bound() 方法的返回值等价,pair.second 和 upper_bound() 方法的返回值等价。也就是说,该方法将返回一个范围,该范围中包含的键为 key 的键值对(map 容器键值对唯一,因此该范围最多包含一个键值对)。
empty() 若容器为空,则返回 true;否则 false。
size()返回当前 map 容器中存有键值对的个数。
max_size()返回 map 容器所能容纳键值对的最大个数,不同的操作系统,其返回值亦不相同。
operator[]map容器重载了 [] 运算符,只要知道 map 容器中某个键值对的键的值,就可以向获取数组中元素那样,通过键直接获取对应的值。
at(key)找到 map 容器中 key 键对应的值,如果找不到,该函数会引发 out_of_range 异常。
insert()向 map 容器中插入键值对。
erase()删除 map 容器指定位置、指定键(key)值或者指定区域内的键值对。后续章节还会对该方法做重点讲解。
swap()交换 2 个 map 容器中存储的键值对,这意味着,操作的 2 个键值对的类型必须相同。
clear()清空 map 容器中所有的键值对,即使 map 容器的 size() 为 0。
emplace()在当前 map 容器中的指定位置处构造新键值对。其效果和插入键值对一样,但效率更高。
emplace_hint()在本质上和 emplace() 在 map 容器中构造新键值对的方式是一样的,不同之处在于,使用者必须为该方法提供一个指示键值对生成位置的迭代器,并作为该方法的第一个参数。
count(key)在当前 map 容器中,查找键为 key 的键值对的个数并返回。注意,由于 map 容器中各键值对的键的值是唯一的,因此该函数的返回值最大为 1。

--------------------------------------------------------------------- 

给出一个无头单向不循环链表的首结点l,和一个数据val,把链表中所有等于val的节点删除,并返回新的首结点。

struct llist_node {
    int val;
    struct llist_node *next;
};

struct llist_node *func(struct llist_node *l, int val)
{
    struct llist_node *cur = l;        // 指向当前节点
    struct llist_node *back = NULL;    //指向当前节点的前一个位置
    
    while (NULL != cur) {
        if (val == cur->val) {
            if (NULL == back) {
                l = cur->next;
                free(cur);
                cur = l;
            } else {
                back->next = cur->next;
                free(cur);
                cur = back->next;
            }
        } else {
            back = cur;
            cur = cur->next;
        }
    }
    return l;
}

--------------------------------------------------------------------- 

        4、迭代器(Iterators)

                1)介绍

                        迭代器是指针的一种泛化,允许C++程序使用统一的方式来处理不同的数据结构。

                它可以是任意类型的对象,在迭代器这个类中有3个指针

                        【1】一个指向结构的第一个元素的地址

                        【2】一个指向结构的最后一个元素的下一个位置的地址

                        【3】一个指向当前访问元素的地址

                不管是数组还是可变长数组或链表,我们都可以通过迭代器进行结构的访问,他可以访问所有的容器。

                2)分类

                        在C++官方手册中把迭代器分为了5类                        

Input输入迭代器
Forward向前迭代器
Bidirectional双向迭代器
Random Access随机访问迭代器
Output输出迭代器

                在迭代器的函数里,我们可以找到begin()和end()

                        begin获取容器的第一个成员

                        end获取容器的最后一个成员的下一个位置            

                3)通用功能

                        【1】比较两个迭代器是否相等(==、!=)

                        【2】前置和后置递增运算(++)

                        【3】读取元素的解引用运算符(*),只能读取元素,解引用只能出现在赋值运算符的右边

                        【4】箭头运算符(->),解引用迭代器,并提取对象的成员

                4)输入迭代器

                        功能:

                                通用的四种功能

                                只能利用迭代器进行输入功能

                                只能用于单遍扫描算法

                5)输出迭代器

                        功能:

                                通用四种功能

                                只能利用迭代器进行输出功能

                                只能用于单遍扫描算法

                6)前向迭代器

                        功能:

                                通用的四种功能

                                能利用迭代器进行输入和输出功能

                                能用于多遍扫描算法

                7)双向迭代器

                        功能:

                                通用的四种功能

                                能利用迭代器进行输入和输出功能

                                能用于多遍扫描算法

                                前置和后置递减运算(--),这意味着它能够双向访问

                8)随机访问迭代器

                        功能:

                                通用的四种功能

                                能利用迭代器进行输入和输出功能

                                前置和后置递减运算(--),这意味着它能够双向移动

                                比较两个迭代器相对位置的关系运算符(<、<=、>、>=)

                                支持和一个整型数值的加减运算(+、+=、-、-=)

                                两个迭代器上的减法运算符(-),得到两个迭代器的距离

                                支持下标运算符(iter[n]),访问距离其实迭代器n个距离的迭代器指向的元素

                                能用于多遍扫描算法。在支持双向移动的基础上,支持前后位置的比较,随机存取,直接移动n个距离

                9)总结
输入迭代器提供对数据的只读访问只读,支持++、==、!=
输出迭代器提供对数据的只写访问只写,支持++
前向迭代器提供读写操作,并能向前推进迭代器读写,支持++、==、!=
双向迭代器提供读写操作,并能向前和向后推进迭代器读写,支持++、--
随机访问迭代器提供读写操作,并能跳跃式的访问容器的任意数据读写,支持++、--、[n]、-n、<、<=、>、>=
                10)常用容器的迭代器

                        vector:随机访问迭代器

                        deque:随机访问迭代器

                        list:双向迭代器

                        set / multiset:双向迭代器

                        map / multimap:双向迭代器

                        stack:不支持迭代器

                        queue:不支持迭代器

                11)实例(双向迭代器和随机访问迭代器)
                        双向迭代器                        
void text()
{
	list<int> lst;
	for (int i = 0; i < 10; ++i)
	{
		lst.push_back(i);
	}
	list<int>::iterator it;//创建list的迭代器
	cout << "遍历lst并打印: ";
	for (it = lst.begin(); it != lst.end(); ++it)//用 != 比较两个迭代器
	{
		cout << *it << " ";
	}
	//此时it=lst.end(),这个位置是最后一个元素的下一个位置,没有存储数据
	--it;//等价于it--,回到上一个位置
	//it -= 1; //报错,虽然都是-1,但这种方式是随机迭代器才有的功能
	cout << "\nlst的最后一个元素为:" << *it << endl;
}

            对于迭代器来说,-= 与 -- 是不同的,+=++ 也是不同的,它们实现的是不同的功能 。

                        随机访问迭代器
void text()
{
    vector<int> v;
    for (int i = 0; i < 10; ++i)
    {
        v.push_back(i);
    }
    vector<int>::iterator it;
    for (it = v.begin(); it != v.end(); ++it) //用 != 比较两个迭代器
    {
        cout << *it << " ";
    }
    cout << endl;
    for (it = v.begin(); it < v.end(); ++it) //用 < 比较两个迭代器
    {
        cout << *it << " ";
    }
    cout << endl;
    it = v.begin();//让迭代器重新指向首个元素的位置
    while (it < v.end())//间隔一个输出
    { 
        cout << *it << " ";
        it += 2; // 用 += 移动迭代器
    }
    cout << endl;

    it = v.begin();
    cout << it[5] << endl; //用[]访问
}

对于vector来说,其迭代器有失效的可能,vector容器具有动态扩容的功能,每当容器的容量不足时,vector就会进行动态扩容,动态扩容不是在原来的空间后面追加空间,而是在寻找一段新的更大的空间,把原来的元素复制进去,这样一来,容器存储元素的位置就改变了,原来的迭代器还是指向原来的位置,因此每次动态扩容后原来的迭代器就会失效。 

                12)迭代器中的辅助函数(<algorithm>)

                        advance(it, n);        是迭代器it向前或向后移动n个元素

                        distance(it1, it2);     计算两个迭代器之间的距离,即迭代器it1经过多少次++操作后和迭代器it2相等(如果调用时it1已经指向it2的后面,则函数陷入死循环)

                        iter_swap(it1, it2);   用于交换两个迭代器it1、it2指向的值

#include <algorithm>

void text1()
{
    int a[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
    list<int> lst(a, a + 10);
    list<int>::iterator it1 = lst.begin();

    advance(it1, 2);  //it1向后移动两个元素,指向3
    cout << "当前it1指向的元素:" << *it1 << endl;  //输出3
    advance(it1, -1);  //it1向前移动一个元素,指向2
    cout << "当前it1指向的元素:" << *it1 << endl;  //输出2

    list<int>::iterator it2 = lst.end();
    it2--;  //it2指向最后一个元素的位置,即10的位置
    cout << "it1和it2的距离" << distance(it1, it2) << endl;  //输出8

    cout << "交换前打印:";
    for (it1 = begin(lst); it1 != end(lst); ++it1)
    {
        cout << *it1 << " ";
    }
    it1 = begin(lst);
    iter_swap(it1, it2); //交换 1 和 10
    cout << "\n交换后打印:";
    for (it1 = begin(lst); it1 != end(lst); ++it1)
    {
        cout << *it1 << " ";
    }
    cout << endl;
}

         

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值