參加競賽你至少了解這些常用STL內置函數

 

Standard Template Library 標準模板庫

使用其中算法需要 #include<algorithm>

一、sort

a爲數組a[]
T爲元素類型 
n1,n2都是int類型的表達式,可包含變量 

sort(a+n1,a+n2); 
將數組中下標範圍爲[n1,n2)的元素從小到大排序

sort(a+n1,a+n2,greater<T>()) ;
將數組中下標範圍爲[n1,n2)的元素從大到小排序

sort(a+n1,a+n2,Rule());
Rule爲排序規則結構名 
將T類型的數組中下標範圍爲[n1,n2)的元素按照自定義的排序規則排序

 排序規則結構的定義方式:

1)

用例:對數組a前10個元素排序

sort(a,a+10,Rule());

struct Rule{
	bool operator()(const T & a1,const T & a2) const
	{
                return    ;
	} 
} ;

 

struct Rule1{	//按從大到小排序 
	bool operator()(const int & a1,const int & a2) const
	{
		return a1>a2;
	} 
} ;

 

struct Rule2{	//按個位數從小到大排序 
	bool operator()(const int & a1,const int & a2) const
	{
		return a1%10 < a2%10;
	} 	
} ;

2)

用例:對數組a前10個元素排序

sort(a,a+10,Rule);

bool	Rule(    參數列表    )
{
	return	;
}


bool    Rule(int x,int y)    //從大到小排序
{
    return x>y;
}

bool cmp(int a,int b)            //按照正整數各位數字和從小到大排序
{
	int suma=0,sumb=0;
	while(a)
	{
		suma+=a%10;
		a/=10;
	}
	while(b)
	{
		sumb+=b%10;
		b/=10;
	}
	if(suma==sumb)
		return a<b;
	else
		return suma<sumb;
}

 用法代碼呈現:

#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
const double EPSILON=1e-6;
double num[105];
bool cmp(double a,double b)
{
	double da=fabs(a-round(a));
	double db=fabs(b-round(b));
	if(fabs(da-db)<EPSILON)
		return a<b;
	return da<db;
}
int main()
{
	int N;
	scanf("%d",&N);
	for(int i=0;i<N;++i)
		scanf("%lf",&num[i]);
	sort(num,num+N,cmp);
	for(int i=0;i<N;++i)
	{
		if(i!=N-1)
			printf("%lf ",num[i]);
		else
			printf("%lf\n",num[i]);
	}
	return 0;
}

二、二分查找法

binary_search、lower_bound、upper_bound

find(x):在排序容器中找一個元素y,“x必須在y前面”和“y必須在x前面”都不成立 
find(x):在排序容器中找一個元素y,“x必須在y前面”和“y必須在x前面”都不成立 
find(x):在排序容器中找一個元素y,“x必須在y前面”和“y必須在x前面”都不成立 

a爲數組a[]
T爲元素類型 
n1,n2都是int類型的表達式,可包含變量 
number爲要查找的數 
Rule爲自定義排序規則 


binary_search(a+n1,a+n2,number)
在從小到大排好序的基本類型數組上進行二分查找 
在下標範圍爲[n1,n2)的數組中查找“等於”number的元素
返回值爲true或false 


binary_search(a+n1,a+n2,number,Rule())
在用自定義排序規則排好序的,元素爲任意的T類型數組上進行二分查找 
在下標範圍爲[n1,n2)的數組中查找“等於”number的元素
返回值爲true或false 


lower_bound(a+n1,a+n2,number)
T *lower_bound(a+n1,a+n2,number)
在對元素類型爲T的從小到大排好序的基本類型的數組中進行查找
返回指針T *p
*p是查找區間裏下標最小的,大於等於“number”的元素。如果找不到,p指向下標爲n2的元素 


lower_bound(a+n1,a+n2,number,Rule())
T *lower_bound(a+n1,a+n2,number,Rule())
在元素類型任意的T類型、按照自定義排序規則排好序的數組中進行查找
 返回指針T *p
*p是查找區間裏下標最小的,按自定義排序規則,可以排在“number”後面的的元素。如果找不到,p指向下標爲n2的元素 


upper_bound(a+n1,a+n2,number)
T *upper_bound(a+n1,a+n2,number) 
在對元素類型爲T的從小到大排好序的基本類型的數組中進行查找
返回指針T *p
*p是查找區間裏下標最小的,大於“number”的元素。如果找不到,p指向下標爲n2的元素 


upper_bound(a+n1,a+n2,number,Rule())
T *upper_bound(a+n1,a+n2,number,Rule())
在元素類型任意的T類型、按照自定義排序規則排好序的數組中進行查找
返回指針T *p
*p是查找區間裏下標最小的,按自定義排序規則,必須排在“number”後面的的元素。如果找不到,p指向下標爲n2的元素 

三、排序容器:multiset、set

注意,在C++中遍歷set是從小到大遍歷的,也就是說set會幫我們排序

set經常會配合結構體來使用。set是需要經過排序的。系統自帶的數據類型有默認的比較大小的規則,而我們自定義的結構體,系統是不知道這個結構體比較大小的方式,所以我們需要用一種方式來告訴系統如何比較這個結構體的大小。其中一種方法叫做運算符重載,我們需要重新定義小於號。

 用法代碼呈現: 

/*
find(x):在排序容器中找一個元素y,“x必須在y前面”和“y必須在x前面”都不成立 
find(x):在排序容器中找一個元素y,“x必須在y前面”和“y必須在x前面”都不成立 
find(x):在排序容器中找一個元素y,“x必須在y前面”和“y必須在x前面”都不成立 
*/ 
#include<iostream>
#include<cstring>	
#include<set>					//使用multiset和set需要此頭文件 
using namespace std;
int main()
{
	multiset<int> st;			//multiset中可以有重複元素 
	int a[10]={1,14,12,13,7,13,21,19,8,8};
	for(int i=0;i<10;++i)
		st.insert(a[i]);		//插入的是a[i]的複製品
	multiset<int>::iterator i;
	/*
	multiset<T>::iterator p; 
	迭代器,近似於指針,可用於指向multiset中的元素。
	訪問multiset中的元素要通過迭代器 
	multiset上的迭代器可++,--,用==和!=比較,不可比大小,加減整數、相減。 
	*/
	for(i=st.begin();i!=st.end();++i)
		cout<<*i<<",";
	/*
	multiset<T> st;
	st.begin()返回值類型爲multiset<T>::iterator,是指向st中頭一個元素的迭代器
	st.end()返回值類型爲multiset<T>::iterator,是指向st中最後一個元素後面的迭代器
	
	*/
	cout<<endl; 
	i=st.find(22);					//查找返回值爲迭代器 
	if(i==st.end())					//找不到返回值爲end() 
		cout<<"not found"<<endl;
	st.insert(22);
	i=st.find(22);
	if(i==st.end())
		cout<<"not found"<<endl;
	else
		cout<<"found:"<<*i<<endl;	//找到返回指向找到元素的迭代器 
	i=st.lower_bound(13);
	/*
	1,7,8,8,12,13,		13,14,19,21 
	返回最靠後的迭代器it,使得[begin(),it)中的元素都在13前面 
	*/ 
	cout<<*i<<endl;					//輸出13
	i=st.upper_bound(8);
	/*
	1,7,8,8,	12,13,13,14,19,21 
	返回最靠前的迭代器it,使得[it,end())中的元素都在8後面 
	*/
	cout<<*i<<endl;					//輸出12
	st.erase(i);					//刪除迭代器i指向的元素,即12
	for(i=st.begin();i!=st.end();++i)
		cout<<*i<<",";
	cout<<endl;
	return 0; 
}
#include<iostream>
#include<cstring>	
#include<set>					
using namespace std;
//自定義排序規則的multiset用法
struct Rule1
{
	bool operator()(const int & a,const int & b) const
	{
		return (a%10)<(b%10);
	}
};
int main()
{
	multiset<int,greater<int> > st;	    //排序規則爲從大到小
	int a[10]={1,14,12,13,7,13,21,19,8,8};
	for(int i=0;i<10;++i)
		st.insert(a[i]);
	multiset<int,greater<int> >::iterator i;
	for(i=st.begin();i!=st.end();++i)
		cout<<*i<<",";
	cout<<endl;
	multiset<int,Rule1> st2;	    //個位數小的排前面
	for(int i=0;i<10;++i)
		st2.insert(a[i]);
	multiset<int,Rule1>::iterator p;
	for(p=st2.begin();p!=st2.end();++p)
		cout<<*p<<",";
	cout<<endl;
	p=st2.find(133);
	cout<<*p<<endl;			    //輸出13 
	return 0; 
}
#include<iostream>
#include<cstring>	
#include<set>					
using namespacec std;
int main()
{
	set<int> st;
	int a[10]={1,2,3,8,7,7,5,6,8,12};
	for(int i=0;i<10;++i)
		st.insert(a[i]);
	cout<<st.size()<<endl;		    //輸出8
	set<int>::interator i;
	for(i=st.begin();i!=st.end();++i)
		cout<<*i<<",";		    //輸出1,2,3,5,6,7,8,12, 
	cout<<endl;
	pair<set<int>::iterator,bool> result=st.insert(2);
	/*
	pair<T1,T2>類型等價於
	struct{
		TI first;
		T2 second;
        }; 

	pair<set<int>::iterator,bool>等價於
	struct{
	set<int>::iterator first;
	bool second;
        }; 
	*/
	if(!result.second)		    //插入不成功,迭代器指向與要插入元素相同的元素 
		cout<<*result.first<<"already exists"<<endl;
	else
		cout<<*reslut.first<<"instered."<<endl;
	return 0;
} 

例題:蒜頭君破案
問題描述:
最近某地連續發生了多起盜竊案件,根據監控和路人提供的線索得知,這是一個犯罪團伙.並且還知道這個犯罪團伙中每個人的身高、體重、年齡。
警察想知道這個犯罪團伙中的每個人是不是本市的(如果本市有這個特徵的人就視爲是本市的)。
但本市人口太多,又不能一個一個排查,警察又急需這條信息來縮小範圍,所以誓察特來找到聰明的你來幫忙解決這個棘手的問題。
輸入格式:
第一行將會輸入兩個數字n、m。n代表本市的人口數目,m 代表犯罪團伙的數量。
後面n行每行有3個數字代表本市每個人的身高、體重、年齡。
然後會有m行每行有3個數字代表犯罪團伙每個人的身高、體重、年齡。

#include<iostream>
#include<set>
using namespace std;
struct People{
	int height;
	int weight;
	int age;
	People(int _height,int _weight,int _age)
	{
		height=_height;
		weight=_weight;
		age=_age;
	}
};
struct Rule{
	bool operator()(const People & a1,const People & a2)const
	{
		if(a1.height!=a2.height)
			return a1.height>a2.height;
		else if(a1.weight!=a2.height)
			return a1.weight>a2.weight;
		else
			return a1.age>a2.age;
	}
};
set<People,Rule> s;
int main()
{
	int n,m;
	int height,weight,age;
	cin>>n>>m;
	for(int i=0;i<n;++i)
	{
		cin>>height>>weight>>age;
		s.insert(People(height,weight,age));
	}
	for(int i=0;i<m;++i)
	{
		cin>>height>>weight>>age;
		if(s.count(People(height,weight,age)))
			cout<<"yes"<<endl;
		else
			cout<<"no"<<endl;
	}
	return 0;
}

四、排序容器:multimap、map

 

用法代碼呈現:

/*
multimap 
multimap容器中的元素,都是pair形式的
multimap<T1,T2> mp;
mp中的元素都是如下類型:
struct
{
	T1 first;	//關鍵字 
	T2 second;	//值 
};
multimap中的元素按照first排序,並可以按照first進行查找 
*/
/*
一個學生成績錄入和查詢系統 ,接受以下兩種輸入:
Add name id score
Query score 
查詢輸出已有記錄中分數比score低的最高分獲得者的信息
如果有多個學生滿足條件,輸出學號最大的學生的信息 
*/
#include<iostream>
#include<map>
#include<cstring>
using namespace std;
struct StudentInfo{
	int id;
	char name[20];
};
struct Student{
	int score; 
	StudentInfo info;
};
typedef multimap<int,StudentInfo> MAP_STD;
int main()
{
	MAP_STD mp;
	Student st;
	char cmd[20];
	while(cin>>cmd)
	{
		if(cmd[0]=='A')
		{
			cin>>st.info.name>>st.info.id>>st.score;
			mp.insert(make_pair(st.score,st.info));
			/*
			make_pair生成一個pair<int,StudentInfo>變量
			其first等於st.score,second等於st.info 
			*/
		}
		else if(cmd[0]=='Q')
		{
			int score;
			cin>>score;
			MAP_STD::iterator p=mp.lower_bound(score);	
			//查找分數比score低的最高分	
			//[begin(),p)範圍中每一個元素都是比score低的分數 ,p指向的元素分數不會比score低 
			if(p!=mp.begin())
			{
				--p;
				score=p->first;								//比要查詢分數低的最高分 
				MAP_STD::iterator maxp=p;
				int maxID=p->second.id;
				for(;p!=mp.begin()&&p->first==score;--p)	//遍歷所有成績和score相等的學生 
				{
					if(p->second.id>maxID)
					{
						maxp=p;
						maxID=p->second.id;
					}
				}
				if(p->first==score)				
				//如果上面的循環是因爲p==mp.begin()而終止,則p指向的元素還要處理 
				{
					if(p->second.id>maxID)
					{
						maxp=p;
						maxID=p->second.id;	
					}	
				} 
				cout<<maxp->second.name<<" "<<maxp->second.id<<" "<<maxp->first<<endl;
			}//if(p!=mp.begin())
			else
				cout<<"Nobody"<<endl;
			//lower_bound的結果就是begin,說明沒人分數比查詢分數低 
		}//else if(cmd[0]=='Q') 
	}//while(cin>>cmd)
	return 0;
}
/*
map
map中不能有關鍵字重複的元素		重複:A和B都可以排在前面 
可以使用[],下標爲關鍵字,返回值爲first和關鍵字相同的元素的second
插入元素可能失敗
*/ 
#include<iostream> 
#include<map>
#include<string>
using namespace std;
struct Student{
	string name;
	int score;
};
Student students[5]={{"jack",89},{"tom",74},{"cindy",87},{"alysa",87},{"micheal",98}};
typedef map<string,int> MP;
int main()
{
	MP mp;
	for(int i=0;i<5;++i)
		mp.insert(make_pair(students[i].name,students[i].score));
	cout<<mp["jack"]<<endl;		//輸出89 
	mp["jack"]=60;				//修改名爲“jack”的元素的second 
	for(MP::iterator i=mp.begin();i!=mp.end();++i)
		cout<<"("<<i->first<<","<<i->second<<") ";
	cout<<endl;
	Student st;
	st.name="jack";
	st.score=99;
	pair<MP::iterator,bool> p=mp.insert(make_pair(st.name,st.score));
	if(p.second)
		cout<<"("<<p.first->first<<","<<p.first->second<<") inserted"<<endl;
	else
		cout<<"insertion failed"<<endl;
	mp["harry"]=78;		//插入一元素,其first爲"harry",然後將其second改爲78 
	MP::iterator q=mp.find("harry");
	cout<<"("<<q->first<<","<<q->second<<")"<<endl;
	return 0;	
}
/*
輸入大量單詞,每個單詞一行,不超過20個字符,沒有空格。
按出現次數從多到少輸出這些單詞及其出現次數
出現次數相同的,字典序靠前的在前面 
*/ 
#include<iostream>
#include<map>
#include<set>
#include<string>
using namespace std;
struct Word{
	int times;
	string wd;
}; 
struct Rule{
	bool operator()(const Word & w1,const Word & w2)const
	{
		if(w1.times!=w2.times)
			return w1.times>w2.times;
		else
			return w1.wd<w2.wd;
	}
};
int main()
{
	string s;
	set<Word,Rule> st;
	map<string,int> mp;
	while(cin>>s)
		++mp[s];	//mp[]返回元素second 
	for(map<string,int>::iterator i=mp.begin();i!=mp.end();++i)
	{
		Word tmp;
		tmp.wd=i->first;
		tmp.times=i->second;
		st.insert(tmp);
	}
	for(set<Word,Rule>::iterator i=st.begin();i!=st.end();++i)
		cout<<i->wd<<" "<<i->times<<endl;
	return 0;	
}

 map又二維的用法:二維的map不僅可以map套map,還能map套set:

五、queue

queue的頭文件:#include<queue>

queue的基本操作:
1.入隊:如q.push(x):將x元素接到隊列的末端;
2.出隊:如q.pop() 彈出隊列的第一個元素,並不會返回元素的值;
3,訪問隊首元素:如q.front()
4,訪問隊尾元素:如q.back();
5,訪問隊中的元素個數:如q.size();
6.判斷隊列是否爲空:q.empty()

六、vector

動態數組(不定長數組)vector:數組的長度根據需要動態改變
vector的頭文件#include<vector>

vector<T> vec    定義了一個名爲vec的存儲T類型數據的動態數組    初始時vec是空的
C++通過push_back()方法在數組最後面插入一個新的元素    vec.push_back();
C++通過pop_back()方法刪除動態數組的最後一個元素    vec.pop_back();
C++通過clear()方法清空vector,但並不會清空開的內存    vec.clear();
C++通過        vector<int> v;
        vector<int>().swap(v);    清空vector的內存

vector<T> vec(a1,a2);
通過一個構造函數快速建立一個動態數組。(構造函數:在定義一個對象的時候給它賦予初始值)
上面的代碼,調用構造函數,a1爲初始的動態數組的長度,a2爲初始數組中每個元素的值,如果不傳入a2,那麼初始的值都是0

二維動態數組
vector< vector<int> > vec2;
二維動態數組的每一維的長度都可以不一樣。
藉助構造函數,快速構造一個n行m列的動態數組,每個元素的初始值是0:vector< vector<int> > vec2(n,vector<int>(m,0));

用例代碼展示:

鋸齒矩陣是指每一行包含的元素個數不同的矩陣
讀入若干對整數(x,y),表示在第x行的末尾加上一個元素y。
輸出最終的鋸齒數組。初始時矩陣爲空。
輸入格式:
第一行輸入兩個整數n,m(1<=n,m<=10000),n表示鋸齒數組的行數,m表示插入的元素總數
接下來一共m行,每行兩個整數x,y(1<=x<=n,0<=y<=10000)

#include<iostream>
#include<vector>
using namespace std;
vector<int> mat[10005];
int main()
{
	int n,m,x,y;
	cin>>n>>m;
	for(int i=0;i<m;++i)
	{
		cin>>x>>y;
		mat[x].push_back(y);
	}
	for(int i=1;i<=n;++i)
	{
		for(int j=0;j<mat[i].size();++j)
		{
			if(j!=mat[i].size()-1)
				cout<<mat[i][j]<<" ";
			else
				cout<<mat[i][j]<<endl;
		}
                cout<<endl;
	}
	return 0;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章