STL学习总结

    技术2023-12-16  101

    STL学习总结

    一、 泛型程序设计及STL简介

           泛型程序设计是指编写一般化并可重复使用的程序。所谓泛型,其具有多种数据类型上皆可操作的含义,与模板类似。STL是Standard Template Library的简称,中文名标准模板库,是泛型程序设计的代表作品。STL包含很多计算机基本算法和数据结构,而且将算法与数据结构完全分离。STL有三个主要组件:容器、迭代器与算法。

    二、 容器

           容器是存储其他对象的对象。STL的容器主要分为三大类:顺序容器、关联容器和容器适配器。

    1. 顺序容器

           顺序容器是对象的线性集合,所有对象都是同一类型;三种基本顺序容器:向量(vector)、列表(list)、双向队列(deque)。

    (1) Vector

           向(矢)量是一个多功能的、能够存放各种类型对象的类模板,其中的元素是连续存储的。简单地说,vector是数组的一种类表示,它提供了自动内存管理功能,可以动态地改变vector对象长度,并随着元素的添加和删除而增大和缩小。Vector提供了对元素的随机访问。在尾部添加和删除元素的时间是固定的,但在头部或中间插入和删除元素的复杂度为线性时间。 优点:尾部操作和随机访问速度快;缺点:不支持头插、任意位置删除和插入复杂度较高。

    (2) List

           List模板类表示双向链表。除第一个和最后一个元素外,每个元素都与前后的元素相链接,可以双向遍历列表。与vector不同,list在链表中任一位置进行插入和删除的时间都是固定的。List不支持数组表示法和随机访问(没有重载下标运算符“[]”)。从容器中插入或删除元素后,不会移动已有的元素,只是修改链接信息,链表迭代器指向元素将不变。 优点:插入和删除的速度快;缺点:访问速度慢,不支持系统默认的sort排序,内存不连续。

    (3) Deque

           Deque模板类表示在双端队列,是一种可以从双向进行操作的队列。Deque支持随机访问,可以实现向队列尾部或队列首部增添元素,以及从队列尾部或队列首部删除元素,但时间是固定的,而不想vector中那样是线性时间的。 优点:头尾插入和删除以及访问速度快;缺点:按位置插入和删除速度慢。

    (4) 选择容器类型法则

    如果程序要求随机访问元素,则应使用 vector 或 deque 容器。 如果程序必须在容器的中间位置插入或删除元素,则应采用 list 容器。 如果程序不是在容器的中间位置,而是在容器首部或尾部插入或删除元素,则应采用 deque 容器。 如果只需在读取输入时在容器的中间位置插入元素,然后需要随机访问元素,则可考虑在输入时将元素读入到一个 list 容器,接着对此容器重新排序,使其适合顺序访问,然后将排序后的 list 容器复制到一个 vector 容器。

    2. 关联容器

           关联容器是对容器概念的另一个改进。关联容器将值与键关联在一起,并使用键来查找值。关联容器通常有用于确定数据放置位置的算法,以便能够快速检索信息,在查找时具有非常好的性能。但关联容器允许插入新元素,但不能指定元素的插入位置。因为关联容器中的元素是根据关键字存储的。 STL提供了4种关联容器:set、multiset、map和multimap。前两种是在头文件set中定义的,而后两种是在头文件map中定义的。

    (1) Set

    简介:STL set模拟了多个概念,它是关联集合,可反转,可排序,且键是唯一的,所以不能存储多个相同的值。 特点:储存同一类型的数据元素(这点和vector、queue等其他容器相同);每个元素的值都唯一(没有重复的元素);根据元素的值自动排列大小(有序性);无法直接修改元素;高效的插入删除操作。 Multiset类似于set,只是可能有多个值的键相同。

    (2) Map

    简介:映像容器(map)是一种特殊的集合,有时也称为字典(Dictionary)或关联数据(associative array)。map是一种key-value型容器,其中key是关键字,起到索引作用,而value就是其对应的值。Map中要求键key在容器中是唯一的,而其对应的value数据值则可以重复。 特点:map 的所有元素都是 pair,同时拥有实值value和键值key。pair 的第一元素为键值,第二元素为实值;map 不允许两个元素拥有相同的键值;不可以通过 map 的迭代器改变其元素的键值,可以修改元素的实值;当对 map 元素进行增加或删除操作后,原有的迭代器依然有效,被删除的元素的迭代器除外。 Multimap类似于map,其中允许出现相同的键值,但没有重载下标运算符“[]”。

    3. 容器适配器

    队列类型(queue):

           支持先进先出模式的数据存取。让低层展示典型的队列接口。不仅不允许随机访问队列元素,甚至不允许遍历队列。Queue把使用限制在定义队列的基本操作上,可以将元素添加到队尾,从对首删除元素、查看队首和队尾的值、检查元素数目和测试队列是否为空。如果要使用队列中的值,应首先使用front()来检索这个值,然后使用pop()将它从队列中删除。

    栈容器(stack):

           支持先进后出模式的数据存取。给底层提供典型的栈接口。不仅不允许随机访问栈元素,甚至不允许遍历栈。把使用限制在定义栈的基本操作上,即可以将压入推到栈顶、从栈顶弹出元素、查看栈顶的值、检查元素的数目和测试栈是否为空。如果要使用栈中的值,应首先使用top()来检索这个值,然后使用pop()将它从栈中删除。

    优先级队列容器(priority_queue):

           每次从队列中取出的应是具有最高优先级的元素,而优先级则与每一个元素的值相关联。支持操作与queue相同,但最大元素被移到队首,内部底层类是vector。

    三、 迭代器

           迭代器是指针的泛化,是一种检查容器内元素并遍历元素的可带泛型数据类型。迭代器使算法独立于使用的容器类型。所有的第一类容器都定义了相应的迭代器类型,而只有少数的容器支持下标操作;迭代器可以执行++操作;通过对一个迭代器的解引用操作(*),可以访问到容器所包含的元素。在利用迭代器访问元素之前,先要定义迭代器。

    四、 两个编程题:

    1.使用vector存储用户从键盘输入的n个整数,利用stl中的算法,统计出现次数大于2的数据。

    #include<iostream> #include<vector> #include<algorithm> using namespace std; int main() { int n; int i=0; int j=0; cout << "please enter the number of n:" << endl; cin >> n; vector<int>v1(n); vector<int>v2(n); vector<int>v3(n); vector<int>::iterator pos; for (i = 0; i < n; i++) { cin >> v1[i]; } for (i = 0; i < n; i++) { v2[i] = count(v1.begin(), v1.end(), v1[i]); if (v2[i] > 2) { v3[j] = v1[i]; j++; } } pos = unique(v3.begin(), v3.end()); cout << *pos; return 0; } 定义一个英汉翻译词典,存储英文单词和中文词语,提供插入、查找、修改、删除的操作。在此基础上,实现一个简单的英汉翻译器。main函数中输入中文,输出对应的英文单词。 //dictionary.h #ifndef DICTIONARY_H #define DICTIONARY_H #include<iostream> #include<map> #include<string> using namespace std; class Dictionary { public: void out();//全部输出 void del(string word);//删除单词 void add(string word, string explanation);//增加单词 string tran(string);//翻译 private: map<string, string>dic; }; #endif //dictionary.cpp #include<iostream> #include<map> #include<string> #include"dictionary.h" using namespace std; //全部输出 void Dictionary::out() { map<string, string>::iterator it; for (it = dic.begin(); it != dic.end(); it++) { cout << it->first << ":" << it->second << endl; } } //删除单词 void Dictionary::del(string word) { dic.erase(word); } //增加单词 void Dictionary::add(string word, string explanation) { dic.insert(make_pair(word, explanation)); } //翻译 string Dictionary::tran(string word) { if (dic.find(word) != dic.end()) { return dic[word]; } else { return string("no this word"); } } //translation.cpp #include<iostream> #include<map> #include<string> #include"dictionary.h" using namespace std; int main() { Dictionary dt; //添加 dt.add(string("one"), string("一,一个")); dt.add(string("two"), string("二,二个")); dt.add(string("China"), string("中国")); dt.add(string("has"), string("有")); dt.add(string("dut"), string("大连理工大学")); dt.add(string("ssdut"), string("大连理工大学软件学院")); //全部输出 cout << "字典中词汇如下:" << endl; dt.out(); cout << endl; //翻译 cout << "China的意思是:" << endl << dt.tran(string("China")) << endl; cout << "one的意思是:" << endl << dt.tran(string("one")) << endl; cout << "two的意思是:" << endl << dt.tran(string("two")) << endl; cout << "has的意思是:" << endl << dt.tran(string("has")) << endl; cout << "dut的意思是:" << endl << dt.tran(string("dut")) << endl; cout << "ssdut的意思是:" << endl << dt.tran(string("ssdut")) << endl; cout << endl; //删除 dt.del(string("two")); cout << "删除two后,字典的词汇如下:" << endl; dt.out(); cout << endl; return 0; }
    Processed: 0.012, SQL: 9