您的位置:首页 > 其它

STL专题总结!

2017-03-20 23:46 162 查看
       看完《《ACM程序设计基础》》之后,对c++的STL(即 Standard Template Library,标准模板库又称c++泛型库)有了一定的了解,它在std命名空间中定义了常用的数据结构和算法,对我们平时做题来说,使用起来非常方便。

       从根本上说,STL是一些“容器”的集合,这些“容器”有list,
vector,set,map等,STL也是算法和其它一些组件的集合。它们都是c++的重要组成部分。总之,STL提供三种类型的组件:容器,迭代器,算法,它们都支持泛型程序设计标准。 

一、容器    

   首先介绍容器,容器主要有两类:顺序容器和关联容器。其中顺序容器有:vector,list,deque,string等,它们是一系列元素的有序集合。关联容器包括:set,multiset,map和multimap,它包含查找元素的键值。

   1.vector

   vector就是动态数组,vector向量不但能够像数组那样对元素进行随机访问,还能在尾部插入元素,是一种简单高效的容器,完全可以代替数组。Vector存放在一片连续的内存块中,因此它只能向后增长,如果需要在vector的中间插入新元素,则会导致插入位置起后面的所有元素都要往后迁移;另一方面由于它连续存储,因此随机访问元素很方便。

头文件: #include <vector>

定义

vector<data_type> vector_name;

如:vector<int> v;vector<int>v(10);vector<double>v(10,8.6);

操作

  empty() --返回bool型,表示vector是否为空(v.empty())

  size() --返回vector内元素个数(v.size())

  swap()--交换两个容器的内容,vector<string>a,b;   a.swap(b);//交换ab容器中的元素

  push_back(data_type a)将元素a插入最尾端

  pop_back()将最尾端元素删除

  v[i]类似数组取第i个位置的元素(v[0])

begin() --返回一个指向容器中第一个元素的迭代器

end()--返回超过容器尾的迭代器

erase()--删除矢量中给定区间的元素,接受两个迭代器参数,参数指出要删除的区间 例如:vector <double>scores;erase(scores.begin(),scores.begin()+3);

Insert()--操作有三种,它们都必须首先提供插入的位置,表现为一个迭代器,元素将插入到该迭代器指向的位置前,插入的值有三种,一种是一个单值,一种是n个相同的值,最后一种由两个迭代器指定另一容器中的元素的范围。

clear()--清空向量

reverse()--反向排列算法

sort 算法,需要声明头文件"#include<algorithm>",默认对向量元素进行升序排列。
头文件: #include <algorithm>

sort(begin, end);

sort(begin, end, cmp);

例:

  int num[] = {1,5,6,2,9};

  1) sort(num, num + 5);//默认从小到大排序num[]= {1,2,5,6,9};

  2) bool cmp(inta, int b){

  return a > b;//自定义

  }

sort(num, num + 5, cmp);//num[] = {9,6,5,2,1};

find()-- 元素查找,find(v.begin(),v.end(),3);//查找元素3,返回地址值。

元素的访问:

可以用下标的方式访问也可以用迭代器的方式访问。

代码;
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
int main(){
vector<int> a;
for (int i = 0; i < 5; ++i){
a.push_back(5 - i);
}
cout << "Size: " << a.size() << endl;
a.pop_back();
a[0] = 1;
cout << "Size: " << a.size() << endl;
for (int i = 0; i < (int)a.size(); ++i){
cout << a[i] << ", " << endl;
}
cout << endl;
return 0;
}

sort:

#include <bits/stdc++.h>
using namespace std;
int main()
{
int a[10];
vector <int> b;
for(int i=0;i<5;i++)
{
cin>>a[i];
b.push_back(a[i]);
}
sort(a,a+5);
sort(b.begin(),b.end());
for(int i=0;i<5;i++)
cout<<a[i]<<" ";
cout<<endl;
for(int i=0;i<5;i++)
cout<<b[i]<<" ";
return 0;
}

2.string基本字符系列容器

c++STL提供了string基本字符系列容器来处理字符串,它提供了添加、删除、替换、查找和比较等丰富的方法。注意:string容器需要声明头文件 "#include<string>".

(1创建string对象

创建一个字符串对象s,s是一个空字符串,长为0.

#include<bits/stdc++.h>
using namespace std;
int main()
{
string s;
cout<<s.length()<<endl;
return 0;
}
(2给string对象赋值

直接赋值;
#include<string>
#include<iostream>
using namespace std;
int main()
{
string s = "Hello C++STL";
cout<<s<<endl;
return 0;
}
      把字符指针赋给一个字符串对象:

#include<string>
#include<iostream>
using namespace std;
int main()
{
char c[] = "Hello C++STL";
string s = c; //将字符指针赋给一个字符串对象
cout<<s<<endl;
return 0;
}
(3在尾部添加字符串或者字符:

(1)尾部添加一个字符,用“+”

 string s;

 s=s+’a’;

(2)尾部添加一个字符串(两种方式)

    用“+”方式添加:

    string s;

    s=s+”abc”;

    用append()方法添加:

    string s;

    s=s.append(“abc”);

#include<iostream>
#include<string>
#include<cstdio>
#include<algorithm>
using namespace std;
int main()
{
string s="test";
//在尾部添加一个字符
s=s+'1';
cout<<s<<endl;
//尾部添加字符串(直接添加)
s=s+"234";
cout<<s<<endl;
//尾部添加字符串(append方式添加)
s.append("678");
cout<<s<<endl;
return 0;
}
(4在某一位置插入元素:

insert(位置,char);其中,位置用迭代器表示,不是下标。

#include<iostream>
#include<string>
#include<algorithm>
using namespace std;
int main()
{
string s="123";
string ::iterator it=s.begin();
it++;
s.insert(it,'4');
cout<<s<<endl;
return 0;
}
(5访问string对象的元素

一般使用下标方式随机访问string对象的元素,下标是从0开始计数的,string对象的元素是一个字符(char)

当然也可以使用迭代器进行访问,但是string的迭代器一般不用来访问元素,而是对其中的元素进行删除,插入和替换操作的时候作为参数。

#include<bits/stdc++.h>
using namespace std;
int main()
{
string s = "abcde";
cout<<s[2]<<endl;
return 0;
}
(6删除元素:

(1)erase(位置):删除单个元素;

(2)erase(位置1,位置2) :删除区域内的多个元素,其中,位置用迭代器表。注意,不是下标。

#include<iostream>
#include<string>
#include<cstdio>
#include<algorithm>
using namespace std;
int main()
{
string s="1234567";
string ::iterator pos=s.begin();
//删除单个元素
s.erase(s.begin());
cout<<s<<endl;
//删除区间元素
s.erase(s.begin(),s.end());
cout<<endl;
return 0;
}


(7求字符串长度:(1)length();

(2)empty():为空返回1,不为空返回0

#include<iostream>
#include<string>
#include<cstdio>
#include<algorithm>
using namespace std;
int main()
{
string s="1234567";
//字符串长度:
cout<<s.length()<<endl;
//判断字符串是否为空
cout<<s.empty()<<endl;
return 0;
}
(8替换string对象的字符:

使用replace()方法可以很方便的替换string对象中的字符,常用是使用三个参数,第一个是要替换的字符的开始下标,第二个是要替换的字符的个数,第三个是用于替换的字符串。

#include<iostream>
#include<string>
using namespace std;
int main()
{
string s = "abcdefgh";
s.replace(1,3,"xy");
cout<<s<<endl;
return 0;
}


(9查找字符或者字符串:

Find()函数,查找一个字符char或一个子串string,若找到返回找到位置的下标,若没有找到则返回一个值string::npos。

#include<iostream>
#include<string>
#include<cstdio>
#include<algorithm>
using namespace std;  int main()
{
string s="1234567";
int pos=s.find("234");
if(pos!=string::npos)
cout<<"found"<<endl;
else
cout<<"not found"<<endl;
return 0;
}
(10字符串比较:

比较函数 compare(),实际上是按照ASCII的大小比较各个字符串,若两个字符串相等返回0,若第一个字符串大于第二个字符串返回1,反之返回-1。

(11algorithm中提供的算法:

(1)反向排列算法:reverse(位置1,位置2);

(2)排序算法:sort(位置1,位置2,比较函数) ;

(3)计数算法:count(位置1,位置2,字符)。

#include<iostream>
#include<string>
#include<cstdio>
#include<algorithm>
using namespace std;  int main()
{
string s="1234567";
//reverse反向排列
reverse(s.begin(),s.end());
cout<<s<<endl;

string s1="523571";
//sort排序
sort(s1.begin(),s1.end());
cout<<s1<<endl;

string s2="102010230";
//count函数统计字符的个数,例如统计1的个数
int n=count(s2.begin(),s2.end(),'1');
cout<<n<<endl;
return 0;
}
(12分离string中的子串:

sscanf(string ,”格式说明”, 变量地址表列);

#include <stdio.h>
int main ()
{
char sentence []="Tom is 12 years old";
char str [20];
int i;
sscanf (sentence,"%s %*s %d",str,&i);
printf ("%s -> %d\n",str,i);
return 0;
}
输出结果是:Tom -> 12 

3 stack( 栈)和queue(队列)

stack是一种先进后出(FirstInLastOut,FILO)的数据结构,它只有一个出口,只能操作最顶端元素。

queue是一种先进先出(FirstIn First Out, FIFO)的数据结构,从底端加入元素,从顶端取出元素。

队列和堆栈常用的函数有:

void push(const T& t):把t元素压入队尾(栈顶)。

void pop():当队列(栈)非空情况下,删除队头(栈顶)元素。

另外,栈独有的函数:T& top():当栈非空情况下,返回栈顶元素的引用。

队列独有的函数:T& front():当队列非空情况下,返回队头元素的引用; T& back():当队列非空情况下,返回队尾元素的引用。

队列:

头文件: #include <queue>

定义:queue<data_type> queue_name;

  如:queue<int> q;

操作

  empty() --返回bool型,表示queue是否为空(q.empty())

  size() --返回queue内元素个数(q.size())

  front() --返回queue内的下一个元素(q.front())

  back() --返回queue内的最后一个元素(q.back())

  pop() --移除queue中的一个元素(q.pop();)

  push(data_type a) --将一个元素a置入queue中(q.push(a);)
         代码:

#include <iostream>
#include <queue>
#include <algorithm>
using namespace std;
int main(){
queue<int>s;
s.push(1);
s.push(2);
s.push(3);
cout << "Front: " << s.front() << endl;
cout << "Back: " << s.back() << endl;
s.pop();//去顶端
cout << "Size: " << s.size() << endl;
cout << "Front: " << s.front() << endl;
cout << "Back: " << s.back() << endl;
return 0;
}
       栈:

头文件: #include <stack>

定义:stack<data_type>stack_name;

  如:stack<int> s;

操作

  empty() --返回bool型,表示栈内是否为空(s.empty()
)

  size() --返回栈内元素个数(s.size() )

  top() --返回栈顶元素值(s.top())

  pop() --移除栈顶元素(s.pop();)

  push(data_type a) --向栈压入一个元素a(s.push(a); )

代码:

#include <iostream>
#include <stack>
#include <algorithm>
using namespace std;
int main(){

stack<int>s;
s.push(1);
s.push(2);
s.push(3);
cout << "Top: " << s.top() << endl;
cout << "Size: " << s.size() << endl;
s.pop();
cout << "Size: " << s.size() << endl;
if(s.empty()){
cout << "Is empty" << endl;    }
else{        cout << "Is not empty" << endl;    }    	 
return 0;
}
 4.生成排列:

头文件: #include <algorithm>

bool next_permutation(begin, end);

改变区间内元素的顺序,产生下一个排列。

bool prev_permutation(begin, end);

产生前一个排列。

end为最后一个元素的下一个位置。

5.upper_bound 和 lower_bound

upper_bound(begin, end, value);

返回可插入值为value的元素的第一个位置。

lower_bound(begin, end, value);

返回可插入值为value的元素的最后一个位置。

6.set 和 multiset

set 和 multiset会根据特定的排序准则,自动将元素排序,两者的不同之处在于multiset可以允许元素重复而set不允许元素重复。

头文件: #include <set>

定义:set <data_type> set_name;

如:set <int> s;//默认由小到大排序

如果想按照自己的方式排序,可以重载小于号。

struct new_type{

int x, y;

bool operator < (const new_type &a)const{

if(x != a.x) return x < a.x;

return y < a.y;

}

}

set <new_type> s;

 操作:

s.insert(elem) -- 安插一个elem副本,返回新元素位置。

s.erase(elem) -- 移除与elem元素相等的所有元素,返回被移除 的元素个数。

s.erase(pos) -- 移除迭代器pos所指位置上的元素,无返回值。

s.clear() -- 移除全部元素,将整个容器清空。

迭代器举例:

multiset <int> :: iterator pos;

for(pos = s.begin(); pos != s.end(); pos++)

代码:

#include <iostream>
#include <set>
#include <algorithm>
using namespace std;
int main(){
set<string>s1;
set<string>::iterator iter1;
s1.insert("abc");
s1.insert("abc");
s1.insert("abc");
s1.insert("bca");
s1.insert("aaa");
cout << "ITERATE:" << endl;
for (iter1 = s1.begin(); iter1 != s1.end(); iter1++){
cout << (*iter1) << endl;
}
cout << "FIND:" << endl;
iter1 = s1.find("abc");
if(iter1 != s1.end()) {
cout << *iter1 << endl;
}else{
cout << "NOT FOUND" << endl;
}
return 0;
}
#include <iostream>
#include <set>
#include <algorithm>
using namespace std;
struct T1{
int key;
int value1, value2;
bool operator<(const T1 &b)const{
return (key < b.key);
}
};
int main(){
set<T1> s;
set<T1> ::iterator iter1;
T1 t={2,33,44};
T1 tt;
tt.key=5;
tt.value1=22;
tt.value2=88;
s.insert(t);
s.insert(tt);
cout << "ITERATE:" << endl;
for (iter1 = s.begin(); iter1 != s.end(); iter1++){
cout << (*iter1) .key<<"  "<< (*iter1).value1<<"  "<< (*iter1).value2<< endl;
}
cout << "FIND:" << endl;
iter1 = s.find(t);
if(iter1 != s.end()) {
cout << (*iter1) .key<<"  "<< (*iter1).value1<<"  "<< (*iter1).value2<< endl;
}else{
cout << "NOT FOUND" << endl;
}
return 0;
}
 5.map和multimap

所有元素都会根据元素的键值自动排序,map的所有元素都是pair,pair的第一个元素被视为键值,第二个元素为实值。map不允许两个元素有相同的键值,但multimap可以。

头文件: #include <map>

定义:map <data_type1, data_type2> map_name;

如:map <string, int> m;//默认按string由小到大排序

操作:

m.size() 返回容器大小

m.empty() 返回容器是否为空

m.count(key) 返回键值等于key的元素的个数

m.lower_bound(key) 返回键值等于key的元素的第一个可安插的位置

m.upper_bound(key) 返回键值等于key的元素的最后一个可安插的位置

m.begin() 返回一个双向迭代器,指向第一个元素。

m.end() 返回一个双向迭代器,指向最后一个元素的下一个 位置。

m.clear() 讲整个容器清空。

m.erase(elem) 移除键值为elem的所有元素,返回个数,对 于map来说非0即1。

m.erase(pos) 移除迭代器pos所指位置上的元素。

直接元素存取:

m[key] = value;

查找的时候如果没有键值为key的元素,则安插一个键值为key的新元素,实值为默认(一般0)。

m.insert(elem) 插入一个元素elem

a)运用value_type插入

map<string, float> m;

m.insert(map<string, float>:: value_type ("Robin", 22.3));

b) 运用pair<>

m.insert(pair<string, float>("Robin", 22.3));

c) 运用make_pair()

m.insert(make_pair("Robin", 22.3));

代码:

#include <map>
#include <algorithm>
using namespace std;
int main(){
map<string, int> m2;
map<string, int>::iterator m2i, p1, p2;
m2["abd"] = 2;
m2["abc"] = 1;
m2["cba"] = 2;
m2.insert(make_pair("aaa", 9));
m2["abf"] = 4;
m2["abe"] = 2;
cout << m2["abc"] << endl;
m2i = m2.find("cba");
if(m2i != m2.end()){
cout << m2i->first << ": " << m2i->second << endl;
}else{
cout << "find nothing" << endl;
}
cout << "Iterate" << endl;
for(m2i = m2.begin(); m2i != m2.end(); m2i++){
cout<< m2i->first << ": " << m2i->second <<endl;
}
return 0;
}
6优先队列(priority_queue)

一个拥有权值观念的queue,自动依照元素的权值排列,权值最高排在前面。缺省情况下,priority_queue是利用一个max_heap完成的

头文件: #include <queue>

定义:priority_queue <data_type> priority_queue_name;

如:priority_queue <int> q;//默认是大顶堆

操作:

q.push(elem) 将元素elem置入优先队列

q.top() 返回优先队列的下一个元素

q.pop() 移除一个元素

q.size() 返回队列中元素的个数

q.empty() 返回优先队列是否为空

#include <iostream>
#include <queue>
#include <algorithm>
using namespace std;
#define pow2(a) ((a)*(a))
#define dist2(x, y) (pow2(x) + pow2(y))
struct coord{
int x, y;
const bool operator<(const coord &b)const{
return (dist2(x, y) < dist2(b.x, b.y));
}
};
int main(){
priority_queue<coord> s;
coord a;
a.x = 3, a.y = 2;
s.push(a);
a.x = 1, a.y = 2;
s.push(a);
a.x = 2, a.y = 2;
s.push(a);
cout << "Size: " << s.size() << endl;
cout << "Top: " << s.top().x << ", " << s.top().y << endl;
s.pop();
cout << "Top: " << s.top().x << ", " << s.top().y << endl;
return 0;
}
  二、迭代器:

迭代器有输入迭代器,输出迭代器,前向迭代器,双向迭代器等。它能够用来遍历标准模板库容器中的部分或全部元素,对我们平时对元素的操作有很大的便利,使用反向迭代器reverse_iterator可以反向遍历集合,输出的结果正好是集合元素的反向排序结果,他需要用到rbegin()和rend()两个方法,它们分别给出了反向遍历的开始位置和结束位置。

   #include <bits/stdc++.h>

    #include<iostream>

    #include <set>

    usingnamespace std;

int main()

{

  set<int>s;

  s.insert(8);

  s.insert(1);

  s.insert(12);

  s.insert(6);

  s.insert(8);

  set<int>::reverse_iterator rit;

  for(rit=s.rbegin();rit!=s.rend();rit++)

  {

      cout<<*rit<<" ";

  }

  cout<<endl;

  return 0;

}

 三.算法

算法部分主要由头文件<algorithm>包含,它可以包含比较(compare)、交换(swap)、查找(find)、遍历操作(iterator)、复制(strcpy)、移除(erase)、反转(reverse)、排序(sort)、合并等等,在c++中,由于算法的存在,给程序的编写提供了很大的便利。

总结:

学习STL,不仅拓展了自己编程的视野,而且还给程序·的编写提供了很大的便利,在运用STL过程中,需要注意一些细节问题,比如·,对集合进行查找时,最好不要用find(),vector完全可以替代数组,而且比数组方便很多。STL功能强大,应该学会灵活运用,对于我来说,应该多做题,多总结,去更好的理解和运用STL,要意识到,STL的运用,比我们在教科书《《c++程序设计基础》》提供了许多简洁有效的方法,所以拓展视野,增强了综合的能力,是对自己一个很大的提高。










                                            
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: