Stl的list容器迭代器的用法1
【STL中的list容器迭代器】 在C++标准模板库(STL)中,`list`容器是一种基于链表的数据结构,它提供了高效的操作插入和删除元素的能力。与`array`、`vector`和`deque`等其他容器不同,`list`容器的迭代器是双向迭代器,而不是随机访问迭代器。 **双向迭代器的理解** 双向迭代器允许程序员向前和向后移动,但不支持通过索引直接访问元素或进行快速跳跃。这反映了链表数据结构的本质,即元素之间通过指针链接,无法像数组那样通过下标快速访问。双向迭代器支持以下操作: 1. `++it`: 前进一个元素。 2. `it++`: 前进一个元素并返回旧的迭代器。 3. `--it`: 后退一个元素。 4. `it--`: 后退一个元素并返回旧的迭代器。 5. `*it`: 访问迭代器所指向的元素。 6. `it == it2` 和 `it != it2`: 比较两个迭代器是否相等或不等。 然而,双向迭代器不支持以下操作: 1. `p1[i]`: 无法通过下标访问元素。 2. `p1 -= i`、`p1 += i`、`p1 + i`、`p1 - i`: 不能进行加减运算以移动到链表中的其他位置。 3. `p1 < p2`、`p1 > p2`、`p1 <= p2`、`p1 >= p2`: 不能进行比较运算来确定迭代器的相对位置。 **list容器的迭代器函数** `list`容器提供了一系列迭代器函数,便于我们操作和遍历容器中的元素: 1. `begin()`: 返回指向容器首元素的迭代器。 2. `end()`: 返回指向容器末尾之后的位置的迭代器,标志着容器的结束。 3. `rbegin()`: 返回指向容器末尾的反向迭代器,相当于正向迭代器向后移动到最后一个元素。 4. `rend()`: 返回指向容器开头之前的反向迭代器,标志着反向遍历的结束。 5. `cbegin()`、`cend()`: 类似于`begin()`和`end()`,但返回常量迭代器,不允许修改元素。 6. `crbegin()`、`crend()`: 类似于`rbegin()`和`rend()`,但返回常量反向迭代器。 **遍历list容器的示例** 下面的代码展示了如何使用`begin()`和`end()`以及`rbegin()`和`rend()`遍历`list`容器的元素: ```cpp #include <iostream> #include <list> using namespace std; int main() { list<char> values {'h','t','t','p',':','/','/','c','.','b','i','a','n','c','h','e','n','g','.','n','e','t'}; // 使用begin()和end()遍历 for (list<char>::iterator it = values.begin(); it != values.end(); ++it) { cout << *it; } cout << endl; // 使用rbegin()和rend()反向遍历 for (list<char>::reverse_iterator rit = values.rbegin(); rit != values.rend(); ++rit) { cout << *rit; } return 0; } ``` 这段程序首先使用正向迭代器遍历`values`容器,并打印出元素,然后使用反向迭代器从后往前遍历并打印。 **插入和删除操作** 由于`list`容器基于链表,所以在任何位置插入或删除元素都具有O(1)的时间复杂度。但是,由于双向迭代器不支持随机访问,因此在特定位置插入或删除元素时,通常需要先找到目标位置的迭代器。例如,`list::insert(it, value)`可以在迭代器`it`指向的位置插入`value`,而`list::erase(it)`会删除迭代器`it`指向的元素。 **自动类型推断与迭代器** C++11引入了`auto`关键字,使得我们可以更简洁地处理迭代器,无需显式指定迭代器类型。在上述示例中,可以将迭代器声明为`auto it = values.begin();`,编译器会自动推断迭代器的正确类型。 `list`容器的迭代器提供了在链表结构中导航和操作元素的手段,虽然不支持随机访问,但其双向性使得在链表中的插入和删除操作更为高效。在实际编程中,了解并熟练使用这些迭代器函数,可以帮助我们更有效地操作`list`容器。