zoukankan      html  css  js  c++  java
  • STL理论基础、容器、迭代器、算法

    一、STL基本概念

    STL(Standard Template Library,标准模板库)是惠普实验室开发的一系列软件的统称。现然主要出现在C++中,但在被引入C++之前该技术就已经存在了很长的一段时间。

    STL的从广义上讲分为三类:算法(algorithm)、容器(container)和迭代器(iterator),容器和算法通过迭代器可以进行无缝地连接。几乎所有的代码都采用了模板类和模板函数的方式,这相比于传统的由函数和类组成的库来说提供了更好的代码重用机会。

    在C++标准中,STL被组织为下面的13个头文 件:<algorithm>、<deque>、<functional>、<iterator>、<vector>、<list>、<map>、<memory>、<numeric>、<queue>、<set>、<stack> 和<utility>。

    STL优点:

    1. STL是C++的一部分,因此不用额外安装什么,它被内建在你的编译器之内。
    2. STL的一个重要特点是数据结构和算法的分离。尽管这是个简单的概念,但是这种分离确实使得STL变得非常通用。例如,在STL的vector容器中,可以放入元素、基础数据类型变量、元素的地址;STL的sort()函数可以用来操作vector,list等容器。
    3. 程序员可以不用思考STL具体的实现过程,只要能够熟练使用STL就OK了。这样他们就可以把精力放在程序开发的别的方面。
    4. STL具有高可重用性,高性能,高移植性,跨平台的优点。
    • 高可重用性:STL中几乎所有的代码都采用了模板类和模版函数的方式实现,这相比于传统的由函数和类组成的库来说提供了更好的代码重用机会。
    • 高性能:如map可以高效地从十万条记录里面查找出指定的记录,因为map是采用红黑树的变体实现的。(红黑树是平横二叉树的一种)
    • 高移植性:如在项目A上用STL编写的模块,可以直接移植到项目B上。
    • 跨平台:如用windows的Visual Studio编写的代码可以在Mac OS的XCode上直接编译。

    二、三大组件介绍

    1、容器

    STL中容器是指存储有限数据元素的一种数据结构。在使用容器之前首先要根据自己使用的数据集和将要对数据结构采取的访问模式,比如增删改查,决定使用STL中的何种容器类型。 

    STL对定义的通用容器分三类:顺序容器关联容器容器适配器

    顺序容器:此种容器元素的位置是由进入容器的时间和地点决定的;

    关联容器:此种容器已经有规则,进入容器的元素的位置不是由进入容器的时间和地点决定的;

    2、迭代器

    我们使用容器的时候,迭代器是一个不可分割的部分。迭代器在STL中用来将算法和容器联系起来,起着一种胶着剂的作用。迭代器是一种检查容器内元素并遍历元素的数据类型。迭代器是一种行为类似指针的对象,它提供类似指针的功能,对容器成员的内容进行访问。

    注意:每个迭代器是和每一个容器绑定的。

    3、算法

    通过有限步骤,解决问题。

    STL提供了大约100个实现算法的模版函数,比如算法for_each将为指定序列中的每一个元素调用指定的函数,stable_sort以你所指定的规则对序列进行稳定性排序等等。这样一来,只要熟悉了STL之后,许多代码可以被大大的化简,只需要通过调用一两个算法模板,就可以完成所需要的功能并大大地提升效率。

    C++通过模板的机制允许推迟对某些类型的选择,直到真正想使用模板或者说对模板进行特化的时候,STL就利用了这一点提供了相当多的有用算法。

    算法部分主要由头文件<algorithm>,<numeric>和<functional>组成。<algorithm>是所有STL头文件中最大的一个(尽管它很好理解),它是由一大堆模版函数组成的,可以认为每个函数在很大程度上 都是独立的,其中常用到的功能范围涉及到比较、交换、查找、遍历操作、复制、修改、移除、反转、排序、合并等等。<numeric>体积很小,只包括几个在序列上面进行简单数学运算的模板函数,包括加法和乘法在序列上的一些操作。<functional>中则定义了一些模板类,用以声明函数对象。

    三、案例:

    #define _CRT_SECURE_NO_WARNINGS
    #include <iostream>
    using namespace std;
    
    //算法:负责统计某个元素的个数
    int mycount(int* start, int* end, int val)
    {
        int num = 0;
        while (start != end)
        {
            if (*start == val)
            {
                num++;
            }
            start++;
        }
        return num;
    }
    
    int main(void)
    {
        //数组 容器
        int arr[] = { 0,1,2,8,7,9,0 };
        int* pStart = arr;//指向元素的第一个元素
        int* pEnd = &(arr[sizeof(arr) / sizeof(int)]);
    
        int num = mycount(pStart, pEnd, 2);
        cout << "num:" << num << endl;
    
        return 0;
    }
    #define _CRT_SECURE_NO_WARNINGS
    #include <iostream>
    #include<vector>//动态数组 可变数组
    #include<algorithm>//算法
    using namespace std;
    
    void PrintVector(int v)
    {
        cout << v << " " ;
    }
    
    //STL基本语法
    void test01()
    {
        //定义一个容器,并且指定这个容器存放的元素类型为int
        vector<int> v;
        v.push_back(10);
        v.push_back(20);
        v.push_back(30);
        v.push_back(40);
    
        //通过STL提供的for_each算法
        //容器提供的迭代器
        //vector<int>::iterator 迭代器类型
        vector<int>::iterator pBegin = v.begin();//第一个元素的位置
        vector<int>::iterator pEnd = v.end();//最后一个元素的下一个的位置
    
        //容器中可能存放基础的数据类型,也可能存放自定义的数据类型
        for_each(pBegin, pEnd, PrintVector);
        cout << endl;
    }
    
    //容器也可存放自定义的数据类型
    class Person
    {
    public:
        Person(int age,int id):age(age),id(id){}
    public:
        int age;
        int id;
    };
    
    
    void test02()
    {
        //创建容器,并且指定容器的元素类型是Person
        vector<Person> v;
        Person p1(10, 20), p2(30, 40), p3(50, 60);
        v.push_back(p1);
        v.push_back(p2);
        v.push_back(p3);
    
        //遍历
        for (vector<Person>::iterator it = v.begin(); it != v.end();it++)
        {
            cout << (*it).age << " " << (*it).id << endl;
        }
    }
    
    //容器存放Person类型指针,并且for_each打印 或者 迭代器方式
    void test03()
    {
        //创建容器,并且指定容器的元素类型是Person*
        vector<Person*> v1;
        Person p1(1, 2), p2(3, 4), p3(5, 6);
        v1.push_back(&p1);
        v1.push_back(&p2);
        v1.push_back(&p3);
    
        //遍历
        for (vector<Person*>::iterator it = v1.begin(); it != v1.end();it++)
        {
            cout << (**it).age << " " << (**it).id << endl;
        }
    }
    
    // 容器嵌套容器 一个容器作为另一个容器的元素
    void PrintVectorNest(vector<int> v)
    {
        vector<int>::iterator pBegin = v.begin();
        vector<int>::iterator pEnd = v.end();
        for_each(pBegin, pEnd, PrintVector);
    }
    
    typedef vector<int>(VECTOR);
    
    void test04()
    {
        vector<vector<int>> v_nest;
        vector<int> v1;
        v1.push_back(100);
        v1.push_back(200);
        v1.push_back(300);
        v1.push_back(400);
    
        vector<int> v2;
        v2.push_back(110);
        v2.push_back(120);
        v2.push_back(130);
        v2.push_back(140);
    
        v_nest.push_back(v1);
        v_nest.push_back(v2);
    
        vector<VECTOR>::iterator pBegin = v_nest.begin();
        vector<VECTOR>::iterator pEnd = v_nest.end();
        for_each(pBegin, pEnd, PrintVectorNest);
        cout << endl;
    }
    
    int main(void)
    {
        test01();
        test02();
        test03();
        test04();
    
        return 0;
    }
  • 相关阅读:
    [C语言嵌入式系统编程修炼] 软件架构与内存操作篇
    [C陷阱和缺陷] 第2章 语法“陷阱”
    DAO是什么技术
    Java泛型:类型擦除
    Java泛型:泛型类、泛型接口和泛型方法
    定义泛型接口
    java,<E>什么意思?
    java List 去重(两种方式)
    java中List集合及其遍历详解
    java 遍历arrayList的四种方法
  • 原文地址:https://www.cnblogs.com/yuehouse/p/10085127.html
Copyright © 2011-2022 走看看