常用STL及其应用

目录

队列(queue)

优先队列(priority_queue)

栈(stack)

栈的典型应用举例1-括号匹配的检验

vector(向量)

set(集合)

string类

map(映射)

map应用举例2-What Are You Talking About

STL中的算法(next_permutation / prev_permutation)

全排列应用举例3

总结


队列(queue)

特点:

1)先进先出(FIFO)

2)从队头删除元素

3)在队尾加入元素

常见操作:

1)判断队列是否为空

2)查询队列大小

3)访问队首元素

4)访问队尾元素

5)加入元素

6)删除元素

STL队列的基本用法

1)创建队列对象:queue<元素类型>队列名;

2)队列添加元素:队列名.push(元素名);

3)去掉队首元素:队列名.pop();

4)访问队首元素:队列名.front();

5)访问队尾元素:队列名.back();

6)判断是否为空:队列名.empty();

7)返回队列大小:队列名.size();

举个例子:

#include<iostream>
#include<queue>
using namespace std;

int a,b,c,d;
queue<int> q;

q=push(1);
q=push(3);
q=push(4);
q.pop();

a=q.front();
b=q.back();
c=q.size();
d=q.empty();

cout<<a<<' '<<b<<' '<<c<<' '<<d<<' '<<endl;

则输出结果为:

3 4 2 0

优先队列(priority_queue)

本质:实现

特点:

1)在队尾加入元素

2)从队头删除元素

3)每次取出的是具有最高优先权的元素(不一定先进先出)

常见操作:

1)判断队列是否为空

2)查询队列大小

3)返回优先权最高的元素

4)加入元素

5)删除元素

STL优先队列的基本用法

1)创建队列对象:priority_queue<元素类型>队列名;

2)队列添加元素:队列名.push(元素名);

3)去掉第一个元素:队列名.pop();

4)判断是否为空:队列名.empty();

5)返回队列大小:队列名.size();

6)访问最优元素:队列名.top();

来看一个实例:

#include<iostream>
#include<queue>
using namespace std;

int main()
{
	priority_queue<int> q;
	int t,a=2,b=5,c=3;
	q.push(a);
	q.push(b);
	q.push(c);
	while(!q.empty()) // q不为空时 
	{
		t=q.top();
		q.pop();
		cout<<t<<endl; 
	}
	
	return 0;
}

则此时输出结果为:

5
3
2

我们再来看一个实例:

#include<iostream>
#include<queue>
using namespace std;

struct T
{
	int x,y,z;
	friend bool operator < (const T &t1,const T &t2)
	// bool operator < (const T t2) const
	{
		return t1.z < t2.z;
	}
	// { return z < t2.z; }
}t;
 
int main()
{
	priority_queue<T> q;
	T a={4,4,3},b={2,2,5},c={1,5,4};
	q.push(a);
	q.push(b);
	q.push(c);
	while(!q.empty()) // q不为空时
	{
		t=q.top();
		q.pop();
		cout<<t.x<<" "<<t.y<<" "<<t.z<<endl;
	}
	
	return 0;
}

输出结果:

2 2 5
1 5 4
4 4 3

--------------------------------------------------------我是分割线----------------------------------------------------------

栈(stack)

特点:

1)先进后出(FILO)

2)栈顶删除元素

3)栈顶加入元素

常见操作:

1)判断栈是否为空

2)查询栈大小

3)访问栈顶元素

4)栈顶加入元素

5)删除栈顶元素

STL的基本用法

1)创建栈对象:stack<元素类型> 栈名;

2)栈顶添加元素:栈名.push(元素名);

3)删除栈顶元素:栈名.pop();

4)访问栈顶元素:栈名.top(); // 要先确保栈非空

5)判断是否为空:栈名.empty();

6)返回栈的大小:栈名.size();

说明:栈和队列一样没有clear之类的函数,如果想要清空一个栈,需要循环调用出栈函数

下面来看两个的实例:

实例1:

#include<iostream>
#include<stack>
using namespace std;

int main()
{
	stack<int> s;
	s.push(1);
	s.push(2);
	s.push(3);
	s.pop();
	cout<<s.top()<<endl;
	s.top()+=3;
	cout<<s.top()<<endl;

    return 0;
}

输出结果:

2
5

实例2:

#include<iostream>
#include<stack>
using namespace std;

int main()
{
	stack<int> s;
	s.push(1);
	s.push(2);
	s.push(3);
	cout<<s.size()<<endl;
	while(!s.empty()) // 栈不为空时 
		s.pop();
	cout<<s.size()<<endl;

	return 0;
}

输出结果为:

3
0

的典型应用-括号匹配的检验

问题描述:给定一个由(、)、[、] 4种符号构成的字符串,判断其中的括号是否匹配。

如果匹配,输出”yes",否则输出"no"。

Sample Input

(()()[(())])

[((]))

Sample Output

yes
no

AC code:

#include<iostream>
#include<stack>
using namespace std;

bool check(string s); // 函数原型声明

int main()
{
	string s;
	while(cin>>s)
	{
		if(check(s))
			cout<<"yes"<<endl;
		else
			cout<<"no"<<endl;
	}

	return 0;
}

bool check(string s)
{
	stack<char> p;
	p.push('#'); // 设置“哨兵”,防止RE
	for(int i=0;i<s.size();i++)
	{
		char c=s[i]; // string的访问方式
		if(c==')')
		{
			if(p.top()!='(')
				return false;
			else
				p.pop();
		}
		
		else if(c==']')
		{
			if(p.top()!='[')
				return false;
			else
				p.pop();
		}
		else
			p.push(c); 
	}
	
	return (p.size()==1); // 是否只剩“哨兵”
}

运行结果

--------------------------------------------------------我是分割线----------------------------------------------------------

vector(向量)

vector向量动态数组

1、向量的定义:vector<int> a;

2、向量初始化

1)vector<int> abc; // 初始化一个size为0的vector(最常用)

2)初始化size,但每个元素值为默认值

vector<int> abc(10); // 初始化了10个默认值为0的元素

3)初始化size,并且设置初始值

vector<int> cde(10,1); // 初始化了10个值为1的元素

STLvector的基本用法

1)取向量首元素的迭代器:向量名.begin();

2)取向量尾元素下一地址:向量名.end();

3)取向量首元素的值:向量名.front();

4)取向量尾元素的值:向量名.back();

5)下标形式访问:int value() = 向量名[0]; // 类似普通数组的访问

6)尾部添加一个元素:向量名.push_back(value); // 最常见操作

7)删除尾部第一个元素:向量名.pop_back();

8)判向量是否为空:向量名.empty();

9)求向量元素个数:向量名.size(); // 实际元素个数,不是容量

10)翻转向量:reverse(a.begin(),a.end());

STLvector的经典应用-邻接表

struct edge
{
        int from,to,value;
}

const int maxn = 1e5+5;
vector<edge> Map[maxn]; // 一维数组相当于二维数组

若用普通二维数组存邻接表,则需要1e10的空间开销,而如果图中实际边数只有1e6,则无疑会造成极大浪费(超内存)。

// 初始化,clear函数是清空向量,不是变成0。

for(int i=0;i<maxn;i++)
        Map[i].clear();

--------------------------------------------------------我是分割线----------------------------------------------------------

set(集合)

数学上的集合的三个特征:

1.确定性(任一元素必须是确定属于或不属于某个集合)

2.互异性(集合中的元素互不相同)

3.无序性(集合中的元素没有先后之分)

set的含义就是集合,它是一个有序的容器,里面的元素都是排序好的,支持插入,删除,查找等操作,所有的操作都是严格在logn时间内完成,效率非常高。

STLset的基本用法

1)set的声明:set<int> s;

2)set的清空:s.clear();

3)插入一个元素x:s.insert(x); // 如果集合中之前没有,则成功插入并自动排序,否则不插入;

4)查询是否有元素x:int hav = s.count(x); // 返回0或1

5)查找x并返回迭代器:set<int>::iterator it = s.find(x);

6)判断是否为空集:bool isempty = s.empty();

7)求集合元素个数:int n = s.size();

8)删除元素x:s.erase(x);

set最主要用途:自动去重并按升序排序;

set只能通过迭代器iterator)访问

例如下面这个代码:

#include<iostream>
#include<set>
using namespace std;

int main()
{
	set<int> st;

	st.insert(3);
	st.insert(5);
	st.insert(2);
	st.insert(3);

	for(set<int>::iterator it = st.begin(); it != st.end(); it++) // 注意,set不支持 it < st.end()的写法
	{
    	printf("%d ",*it);
	}
	
	return 0;
}

显然运行结果为:

2 3 5

这里需要注意,set不支持 it < st.end() 的写法,因为set存储结构为二叉堆,而vector可以写成it<st.end()的形式。为了避免出现混淆,可以选择都写成 it != st.end() 来避免出错。

若要求降序如何实现呢?

代码实现如下:

#include<iostream>
#include<set>
using namespace std;

int main()
{
	set<int,greater<int> > st;
	set<int,greater<int> >::iterator it;

	st.insert(3);
	st.insert(5);
	st.insert(2);
	st.insert(3);

	for(it = st.begin(); it != st.end(); it++) // 注意,set不支持 it < st.end()的写法
	{
    	printf("%d ",*it);
	}
}

此时输出为:

5 3 2

--------------------------------------------------------我是分割线----------------------------------------------------------

string类

一、string对象的声明:

string str;

string strl="qwertyui";

二、求string对象的长度:

string strTest="test";

strTest.length();        // 结果为4

strTest.size();        // 结果为4

三、string对象的连接:

可以使用 + += 运算符对string对象执行字符串的连接操作。
(还有可以 append 成员函数实现字符串连接,这里可以忽略)

四、string对象的比较:

可以用 <、<=、==、!=、>=、> 运算符比较string对象,
(还有 compare 成员函数用于比较字符串,这里可以忽略)

五、求 string 对象的子串:

substr 成员函数可以用于求子串(n,m);

调用时,如果省略m或m超过了字符串的长度,则求出来的字串就是从下标n开始一直到字符串结束的部分。

string s1="this is ok";

string s2=s1.substr(2,4);        // s2 = "is i"

s2=s1.substr(2);        // s2 = "is is ok"

六、插入字符串:

insert 成员函数可以在string对象中插入另一个字符串,返回值为对象自身的引用。

例如:

string s1("Limitless"),s2("00");

s1.insert(2,"123"); // s1 = "Li123mitless"

s1.insert(3,s2); // s1 = "Li10023mitless"

s1.insert(3,5,'X'); // s1 = "Li1XXXXX0023mitless"

七、删除字串:

erase 成员函数可以删除 string 对象中的字串,返回值为对象自身的引用。

例如:

string s1("Real Steel");

s1.erase(1,3);        // s1 = "R Steel"

s1.erase(5);        // s1 = "R Ste"

八、交换两个string对象的内容

swap成员函数可以交换两个string对象的内容:

string s1("West"),s2("East");

s1.swap(s2);

// s1 = "East",s2 = "West"

九、字符串的查找操作:

string str = "The apple thinks apple is delicious"; // 长度为34

string key = "apple";

int pos1 = str.find(key);

int pos2 = str.find(key,10);

// s.find(str) 查找字符串str在当前字符串s中第一次出现的位置

// s.find(str,pos) 查找字符串str在当前字符串s的[pos,end]中第一次出现的位置。

十、用STL算法操作string对象:

string s("afgcbed");

sort(s.begin(),s.end());

cout<<s<<endl; // 输出 abcdefg

next_permutation(s.begin(),s.end());

cout<<s<<endl; // 输出 abcdegf

reverse(s.begin().s.end()); // 翻转字符串

cout<<s<<endl; // 输出 fgedcba

STL中的迭代器

迭代器:遍历容器中数据的对象。对存储于容器中的数据进行处理时,迭代器能按预先定义的顺序从一个成员移向另一个成员。

也就是说,通过迭代器可以在不了解容器内部原理的情况下遍历容器。

总之,迭代器的作用就是提供一个遍历容器内部所有元素的接口,内部有一个与容器相关联的指针,然后重载各种运算操作来实现元素的遍历。

STL中的迭代器-典型用法

#include<iostream>
#include<vector>
using namespace std;

int main()
{
	vector<int> ivec;
	vector<int>::iterator iter;
	ivec.push_back(4);
	ivec.push_back(2);
	ivec.push_back(3);
	
	for(iter=ivec.begin();iter!=ivec.end();iter++)
		cout<<*iter<<endl;
}

输出结果:

4
2
3

--------------------------------------------------------我是分割线----------------------------------------------------------

map(映射)

map是一个键值对(key/value)容器,对于迭代器来说,可以修改value,而不能修改keymap会根据key自动排序。

map类型通常可理解为关联数组:可使用键作为下标来获取一个值。关联的本质在于:元素的值与某个特定的键相关联而并非通过元素在数组中的位置来获取。

STLmap的基本用法

1)map<int,string> m; // 定义一个空map m;

2)m.count(k); // 返回m中键值等于k的元素的个数(1或0)

3)m.find(k); // 存在则返回指向该元素的迭代器,否则返回结束地址end()。

4)m.erase(k); // 删除m中键为k的元素,返回删除元素的个数(1或0)

5)m.erase(p); // 从m中删除迭代器p所指向的元素

6)m.insert(e); // e是一个用在m上的value_type类型的值(一个pair)。

// 如果 e.first 不在m中,则插入一个为 e.second 的新元素;如果该键在m中已存在(只看key,不看value),那么不进行任何操作。

7)m.clear(); // 清空map m;

8)m.empty(); // 判断map m是否为空

下面我们来看几个实例:

STL中map的元素的插入和遍历(1)

/* map元素的插入和遍历 1 */
#include<iostream>
#include<map>
using namespace std;

int main()
{
	map<int,string> mapStudent;
	mapStudent[1]="student_one"; // 方便的数据插入方式
	mapStudent[2]="student_two";
	mapStudent[3]="student_three";
	map<int,string>::iterator iter;
	
	for(iter=mapStudent.begin() ; iter!=mapStudent.end() ; iter++)
	{
		cout<<iter->first<<" "<<iter->second<<endl; // first为键,second为值
	}
	
	return 0;
} 

则运行结果为:

1 student_one
2 student_two
3 student_three

STL中map的元素的插入和遍历(2)

/* map元素的插入和遍历 2 */
#include<iostream>
#include<map>
using namespace std;

int main()
{
	map<string,int> mapStudent;
	mapStudent["student_one"]=1; // 方便的数据插入方式
	mapStudent["student_two"]=2;
	mapStudent["student_three"]=3;
	map<string,int>::iterator iter;
	
	for(iter=mapStudent.begin() ; iter!=mapStudent.end() ; iter++)
	{
		cout<<iter->first<<" "<<iter->second<<endl;
	}
	
	return 0;
}

此时运行结果为:

student_one 1
student_three 3
student_two 2

map的应用

题目链接:Problem - 1075 (hdu.edu.cn)

What Are You Talking About

Problem Description

Ignatius is so lucky that he met a Martian yesterda1075Sy. But he didn't know the language the Martians use. The Martian gives him a history book of Mars and a dictionary when it leaves. Now Ignatius want to translate the history book into English. Can you help him?

Input

The problem has only one test case, the test case consists of two parts, the dictionary part and the book part. The dictionary part starts with a single line contains a string "START", this string should be ignored, then some lines follow, each line contains two strings, the first one is a word in English, the second one is the corresponding word in Martian's language. A line with a single string "END" indicates the end of the directory part, and this string should be ignored. The book part starts with a single line contains a string "START", this string should be ignored, then an article written in Martian's language. You should translate the article into English with the dictionary. If you find the word in the dictionary you should translate it and write the new word into your translation, if you can't find the word in the dictionary you do not have to translate it, and just copy the old word to your translation. Space(' '), tab('\t'), enter('\n') and all the punctuation should not be translated. A line with a single string "END" indicates the end of the book part, and that's also the end of the input. All the words are in the lowercase, and each word will contain at most 10 characters, and each line will contain at most 3000 characters.

Output

In this problem, you have to output the translation of the history book.

Sample Input

START
from fiwo
hello difh
mars riwosf
earth fnnvk
like fiiwj
END
START
difh, i'm fiwo riwosf.
i fiiwj fnnvk!
END

Sample Output

hello, i'm from mars.
i like earth!

AC code:

#include<bits/stdc++.h>
using namespace std;

int main()
{
	string a,b;
	map<string,string>m;
	cin>>a;
	while(cin>>a&&a!="END")
 	{
  		cin>>b;
  		m[b]=a;
 	}
 	cin>>a;
 	char tem[3001];
 	getchar();
 	while(1)
	{
  		gets(tem);
  		if(strcmp(tem,"END")==0)
  			break;
  	    int i,len;
  	    len=strlen(tem);
  	    b="";
      	for(i=0;i<len;i++)
      	{
       		if(tem[i]<'a'||tem[i]>'z')
   	    	{
        		if(m[b]!="")
         			cout<<m[b];
        		else
     	    		cout<<b;
    	    	b="";
    	       	cout<<tem[i];
   		    }
   		    else
   			    b+=tem[i];
  	    }
	    cout<<endl;
    }

	return 0;
}

运行结果

--------------------------------------------------------我是分割线----------------------------------------------------------

STL中的算法(next_permutation)

next_permutation 通常用于生成序列的全排列

例如:

#include<iostream>
#include<algorithm>
using namespace std;

int main()
{
	int a[]={1,2,3};
	do{
		cout<<a[0]<<" "<<a[1]<<" "<<a[2]<<endl;
	}while(next_permutation(a,a+3));

    return 0;
}

运行结果为:

1 2 3
1 3 2
2 1 3
2 3 1
3 1 2
3 2 1

若当前调用排列已经达到最大字典序,比如3,2,1,则函数返回false;

修改函数的参数,比如改为(a,a+2),则可以只对部分长度全排列。(此时只对前两个数字全排列)

与 next_permutation() 相对应的是 prev_permutation() ,即由原排列得到字典序中上一个最近排列。

例如:

#include<iostream>
#include<algorithm>
using namespace std;

int main()
{
	int a[]={3,2,1};
	do{
		cout<<a[0]<<" "<<a[1]<<" "<<a[2]<<endl;
	}while(prev_permutation(a,a+3));

    return 0;
}

此时,运行结果为:

3 2 1
3 1 2
2 3 1
2 1 3
1 3 2
1 2 3

那么next_permutation是如何实现序列的全排列的呢?

算法思想:

从最右边开始,两两比较相邻的元素,直到找到右边比左边大的一对,左边那个就是将要被替换的,再从最右边开始找比这个元素大的第一个,交换他们两个;

交换之后,翻转交换元素的后面的所有元素;

比如:1 3 4 6 5 2 -> 1 3 5 6 4 2 -> 1 3 5 2 4 6

全排列应用举例

问题描述:

给定1到N的序列,我们定义1,2,3...N-1,N是由1到N组成的所有序列中的最小序列(每个数字只能使用一次)。则很容易看出,第二个最小的序列是1,2,3...N,N-1。

现在,给定两个数字N和M,请告诉由数字1到N组成的第M个最小的序列是什么。

Sample Input

6 4

Sample Output

1 2 3 5 6 4

AC code:

#include<iostream>
#include<algorithm>
using namespace std;

int main()  
{
	int N,M,c=0;
	cin>>N>>M;
	int *p=new int [N]; 
    for(int i=0;i<N;i++)
		p[i]=i+1;
    do{
	    c++;
    	if(c==M)
    	{
    		for(int j=0;j<N;j++)
				printf("%d ",p[j]);
			cout<<endl;
			break;
		}
    }while(next_permutation(p,p+N));
    
	return 0;
}

运行结果

 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The End ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

总结

队列(queue)

栈(stack)

向量(vector)

集合(set)

string类(string)

映射(map)

next_permutation()

prev_permutation()

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值