zoukankan      html  css  js  c++  java
  • 实战c++中的vector系列--vector的遍历(stl算法、vector迭代器(不要在循环中推断不等于end())、operator[])

    遍历一个vector容器有非常多种方法。使用起来也是仁者见仁。

    通过索引遍历:

    for (i = 0; i<v.size(); i++)
    {
        cout << v[i] << " ";
    }

    迭代器遍历:

    for (vInt::const_iterator iter = v.begin(); iter != v.end();iter++)
    {
        cout << *iter << " ";
    }

    算法遍历:

    copy(v.begin(), v.end(), ostream_iterator<int>(cout, " "));

    非常多书上推荐的是使用算法进行遍历。

    写了一个简单的程序对上面的三种方法进行了比較:

    #include<iostream>
    #include<vector>
    #include<iterator>
    #include<algorithm>
    #include<time.h>
    #include<windows.h>
    using namespace std;
    typedef vector<int> vInt;
    void print_vec_operator(const vInt & v)//方法一,採用下标訪问
    {
        int i;
        for (i = 0; i<v.size(); i++)
        {
            cout << v[i] << " ";
        }
        cout << endl;
    }
    void print_vec_iterator(const vInt &v)//方法二,採用迭代器訪问
    {
    
        for (vInt::const_iterator iter = v.begin(); iter != v.end();iter++)
        {
            cout << *iter << " ";
        }
        cout << endl;
    }
    void print_vec_algorithm(const vInt &v)//方法三。将容器的内容拷贝到cout绑定的迭代器
    {
        copy(v.begin(), v.end(), ostream_iterator<int>(cout, " "));
        cout << endl;
    }
    
    int main()
    {
        vInt v;
        int i;
        for (i = 0; i<100000; i++)
        {
            v.push_back(i);
        }
        int start_time_print_vec1 = GetTickCount();
        print_vec_operator(v);
        int end_time_print_vec1 = GetTickCount();
    
    
        int start_time_print_vec2 = GetTickCount();
        print_vec_iterator(v);
        int end_time_print_vec2 = GetTickCount();
    
    
        int start_time_print_vec3 = GetTickCount();
        print_vec_algorithm(v);
        int end_time_print_vec3 = GetTickCount();
    
        std::cout << (end_time_print_vec1 - start_time_print_vec1) << endl;
        std::cout << (end_time_print_vec2 - start_time_print_vec2) << endl;
        std::cout << (end_time_print_vec3 - start_time_print_vec3) << endl;
    
        return 0;
    }

    当vector初始化10000个元素时,三种方法的效率不相上下。执行几次时间相差无几:
    //输出:
    //1718 operator[]
    //1735 iterator
    //1797 algorithm

    可是当把veector初始化100000的时候,三种方法的效率就有了较大的差距:
    //输出:
    //20016 operator[]
    //32172 iterator
    //62468 algorithm

    再写一个vector里放一个类:

    #include<iostream>
    #include<vector>
    #include<iterator>
    #include <algorithm>
    #include <functional>
    #include<windows.h>
    
    class AAA
    {
    public:
        void MakeFull2()
        {
        }
    };
    
    int main()
    {
        int nCount = 1000000;
        std::vector< AAA* > vAAA;
        vAAA.resize(nCount);
        for (int i = 0; i < nCount; ++i)
        {
            vAAA[i] = new AAA;
        }
    
        // 时间
        int start, end;
    
        // 測试成员函数调用(std::vector下标訪问方式)
        start = GetTickCount();
        size_t count = vAAA.size();
        for (size_t i = 0; i < count; ++i)
            vAAA[i]->MakeFull2();
        end = GetTickCount();
        std::cout << end - start << std::endl;
    
    
        // 測试成员函数调用(STL算法方式)
        start = GetTickCount();
        std::for_each(vAAA.begin(), vAAA.end(),
            std::mem_fun<void, AAA>(&AAA::MakeFull2));
        end = GetTickCount();
        std::cout << end - start << std::endl;
    
        // 測试成员函数调用(STL迭代器方式)
        start = GetTickCount();
        std::vector< AAA* >::iterator itr_end = vAAA.end();
        for (std::vector< AAA* >::iterator itr = vAAA.begin(); itr != itr_end; ++itr)
            (*itr)->MakeFull2();
        end = GetTickCount();
        std::cout << end - start << std::endl;
    
        // 測试成员函数调用(STL迭代器方式)
        start = GetTickCount();
        for (std::vector< AAA* >::iterator itr = vAAA.begin(); itr != vAAA.end(); ++itr)
            (*itr)->MakeFull2();
        end = GetTickCount();
        std::cout << end - start << std::endl;
        return 0;
    }
    //输出:
    //313 oprator[]
    //62  algorithm
    //422 iterator
    //922  iterator

    再执行一次,结果为:
    //296
    //63
    //594
    //1672

    这个时候使用algorithm+functional进行遍历效率最高。


    个人认为下标索引的方式总是会效率高于迭代器方式。

    以下分析一下两种迭代器方式。为何相差不小呢:

    这就要看一下std::vector::end()的原型了:

    iterator end() _NOEXCEPT
    {   // return iterator for end of mutable sequence
        return (iterator(this->_Mylast(), &this->_Get_data()));
    }

    就是每次推断itr != vAAA.end()的时候,都要进行又一次构造一个迭代器并进行返回。这样当然减少的效率。

  • 相关阅读:
    为啥负利率国债有人抢着买?因为时代变了
    微增长时代
    U盘插入电脑后图标是灰色的,打开提示“请将磁盘插入驱动器”
    计算shell 脚本的执行时间
    win10系统应用商店打开后无法联网 代码: 0x80131500 的解决办法
    Jetbrains家的软件都可用的激活码-pycharm
    postman中x-www-form-urlencoded与form-data的区别
    升级Gogs版本
    上海对售价超1499元的茅台酒即没收并另处罚款
    提高收入的根本途径
  • 原文地址:https://www.cnblogs.com/yfceshi/p/7238463.html
Copyright © 2011-2022 走看看