STL专题总结!

       看完《《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删除元素:

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

2erase(位置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();

2empty():为空返回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.mapmultimap

所有元素都会根据元素的键值自动排序,map的所有元素都是pairpair的第一个元素被视为键值,第二个元素为实值。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来说非01

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++程序设计基础》》提供了许多简洁有效的方法,所以拓展视野,增强了综合的能力,是对自己一个很大的提高。







  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值