STL算法-迭代器

算法和迭代器

原文链接:https://blog.csdn.net/weixin_45389639/article/details/121618243

算法的一般结构

​ algorithm看不见container,所以它所需要的一切信息都必须从iterator获取,而iterator(由container提供)必须要回答algorithm的所有提问container才能搭配该algorithm的所有操作。
在这里插入图片描述

  • STL源码中所有算法都遵循以下格式:
template<typename iterator>
Algorithm(iterator itr1,iterator itr2){
    ...
}

template<typename iterator,typename Cmp>
Algorithm(iterator itr1,iterator itr2,Cmp comp){
    ...
}

迭代器分类

在这里插入图片描述

​ 迭代器的关联类型iterator_category表示迭代器类型,其分类为以下5种:

1.	struct input_iterator_tag{};
2.	struct ouput_iterator_tag{};
3.	struct forward_iterator_tag:public input_iterator_tag{};
4.	struct bidirectional_iterator_tag:public forward_iterator_tag{};
5.	struct random_access_iterator_tag:public bidrectional_iterator_tag{};

​ 采用class而非enum来表示迭代器类型,出于以下两个考量:

使用类继承可以表示不同迭代器类型的从属关系。
STL算法可以根据传入的迭代器类型调用不同版本的重载函数。

void _displayIteratorCategory(random_access_iterator_tag) {
    cout << "random_access_iterator_tag" << endl;
}
void _displayIteratorCategory(forward_iterator_tag) {
    cout << "forward_iterator_tag" << endl;
}
void _displayIteratorCategory(bidirectional_iterator_tag) {
    cout << "bidirectional_iterator_tag" << endl;
}
void _displayIteratorCategory(input_iterator_tag) {
    cout << "input_iterator_tag" << endl;
}
void _displayIteratorCategory(output_iterator_tag) {
    cout << "output_iterator_tag" << endl;
}

template<typename T>
void displayIteratorCategory(T iter) {
    typename iterator_traits<T>::iterator_category cag;
    _displayIteratorCategory(cag);
}

void iteratorCategoryTest() {

    displayIteratorCategory(vector<int>::iterator()); //random_access_iterator
    displayIteratorCategory(array<int,10>::iterator());	//random_access_iterator
    displayIteratorCategory(list<int>::iterator());	//bidirectional_iterator
    displayIteratorCategory(forward_list<int>::iterator());	//forward_iterator
    displayIteratorCategory(deque<int>::iterator());	//random_access_iterator

    displayIteratorCategory(set<int>::iterator());	//bidirectional_iterator
    displayIteratorCategory(map<int,int>::iterator()); //bidirectional_iterator
    displayIteratorCategory(unordered_set<int>::iterator()); //forward_iterator
    displayIteratorCategory(unordered_map<int,int>::iterator()); //forward_iterator

    displayIteratorCategory(istream_iterator<int>()); //input_iterator
    displayIteratorCategory(ostream_iterator<int>(cout,"")); //output_iterator
}

在这里插入图片描述

  • 容器vector、array、deque对使用者来说空间是连续、可跳跃的,所以迭代器是random_access_iterator。
  • 容器list为双向链表,set、map、multimap、multiset本身是有序的,支持双向移动,所以为bidirectional_iterator。
  • 容器forward_list为单向链表容器unordered_set、unordered_map、unordered_multiset、unordered_map哈希表中的每个桶都是单向链表.因此其迭代器只能单向移动,因此是forward_iterator类型。
  • 迭代器istream_iterator和ostream_iterator本质上是迭代器,后文会提到这两个类的源码。

迭代器对算法的影响

​ STL中大部分算法会根据传入的迭代器类型以及其他信息来调用不同的重载函数,针对特定的迭代器调用最优的重载版本。

STL中distance根据不同iterator_category执行不同的重载函数

template<class InputIterator>
inline iterator_traits<InputIterator>::difference_type
_distance(InputIterator first,InputIterator last,input_iterator_tag){
	iterator_traits<InputIterator>::difference_type n=0;
    while(first!=last){
        ++first;
        ++n;
    }
    return n;
}

template<class RandomAccessIterator>
inline iterator_traits<RandomAccessIterator>::difference_type
_distance(RandomAccessIterator first,RandomAccessIterator last,random_access_iterator_tag){
return last-first;}


//这里的iterator_traits<InputIterator>::difference_type 为函数的返回类型,只有在运行的时候才确定是何种类型
template<class InputIterator>
inline iterator_traits<InputIterator>::difference_type
distance(InputIterator first,InputIterator last){
    iterator_traits<InputIterator>::iterator_category category;
}

STL中Advance根据不同iterator_category执行不同的重载函数

templaye<class BidirectionalIterator,class Distance>
inline void _advance(BidirectionalIterator&i,Distance n,bidirectional_iterator_tag){
    if(n>=0){
		while(n--)
            ++i;
    }
    else{
		while(n++)
            --i;
    }
}


templaye<class RandomAccessIterator,class Distance>
inline void _advance(RandomAccessIterator&i,Distance n,random_access_iterator_tag){
    i+=n;
}


template<class InputIterator,class Distance>
inline void advance(InputIterator& i,Distance n){
	_advance(i,n,iterator_category(i));
}

template<class Iterator>
inline typename iterator_traits<Iterator>::iterator_category
iterator_category(const Iterator&){
    typedef typename iterator_traits<Iterator>::iterator_category category;
    return category(); //创建temp category object
}

STL中copy根据不同iterator_category和type traits执行不同的重载函数

在这里插入图片描述

STL中destroy根据不同iterator_category和type traits执行不同的重载函数
在这里插入图片描述

STL算法都是模板函数,无法对传入的iterator_category类型做出限定,但源码中的模板参数名还是对接收的iterator_category做出了一定的暗示。例如在命名模板参数上。

template<class InputIterator>
inline Iterator_traits<InputIterator>::diffrence_type
distance(InputIterator first,InputIterator last){
...
}

template<class ForwardIterator>
inline void rotate(ForwardIterator first,ForwardIterator middle,ForwardIterator last){
...
}

template<class RandomAccessIterator>
inline void sort(RandomAccessIterator first,RandomAccessIterator last){
...
}

template<class InputIterator,class T>
InputIterator find(InputIterator first,InputIterator last,const T&value){
...
}

  • 11
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值