STL和基本数据结构

STL包含:容器,迭代器,空间配置器,配接器,算法,仿函数


1、vector

动态数组,从末尾能快速插入和删除,直接访问任何元素。但是在中间进行插入和删除会造成内存块的复制。如果数组后面的内存空间不够需要重新申请一块足够大的内存。所以时间紧张,所以竞赛的时候就直接用vector吧。

题目 HDU 4841“圆桌问题”

题目分析:可以用vector模拟动态变化的圆桌,赶走n个人下留下的都是好人。但是呢,通过看大佬的博客知道了还有递归可以解决。

代码:递归,公式看代码吧

//递归 old=(new+m-1)%n+1,f(n,m)存活编号与f(n-1,m)
/*1 2 3 ... m-2 m-1 m m+1 m+2 n...
删除m
1 2 3 ... m-2 m-1 m+1 m+2 n...
          n-2 n-1  1   2  3  */
#include<bits/stdc++.h>
using namespace std;
const int m=3;
int main(){
	int n,f=0;
	cin>>n;
	for(int i=1;i<=n;i++)
	f=(f+m)%i;
	cout<<f+1<<endl;
}

牛啊!最强的就是能推出公式来的了直接吊打啊

代码:环形链表

每个人死or活--》bool true/false

期初每个人都是活的 a[]=false

//环形链表 
#include<bits/stdc++.h>
using namespace std;
int main()
{
	bool a[101]={0}; 
	int n,m,i,f=0,t=0,s=0;
	cin>>n>>m;
	do{
		++t;//枚举所有位置 
		if(t>n)
			   t=1;//模拟环状,首尾相连
		if(!a[t])
 				 s++;//t上有人就报数
		if(s == m){
			s=0;//计数器清零
			 cout<<t<<' ';//输出被杀编号
			 a[t]=1;//恢复空
			 f++;//死亡人数+1 
		} 
	}while(f!=n);//所有人被杀 
	return 0;
}

 

代码:STL

#include<bits/stdc++.h>
using namespace std;
int main(){
	vector<int>table;
	int n,m;
	while(cin>>n>>m){
		table.clear();
		for(int i=0;i<2*n;i++)
				table.push_back(i);//初始化
		int pos=0;//记录当前位置 
		for(int i=0;i<n;i++){//赶走N个人 
			pos=(pos+m-1)%table.size();//圆桌是环形,取余处理
			table.erase(table.begin()+pos);//赶走坏人,table人数减一
			 
		} 
		int j=0;
		for(int i=0;i<2*n;i++){//打印预先安排座位 
			if(!(i%50)&&i) cout<<endl;//50个字母一行
			if(j<table.size()&&i==table[j]){//table留下的都是好人
						j++;
						cout<<"G"; 
			} 
			else
						cout<<"B";
		}
		cout<<endl<<endl;//留一个空行 
	}
	return 0;
}

2、栈和stack

栈—》先进后出,说一下爆栈问题处理方式:

1、在程序中调大系统的栈,依赖计算机,所以热身的时候一定要试试机子

2、手工写栈(还没学到以后学到再来补充)

题目 HDU 1062“Text Reverse”

代码:

//翻转字符串,栈
#include<bits/stdc++.h>
using namespace std;
int main()
{
	int n;
	char ch;
	scanf("%d",&n);getchar();
	while(n--)
	{
		stack<char>s;
		while(true){
			ch =getchar();
			if(ch==' '||ch=='\n'||ch==EOF){
				while(!s.empty()){
					printf("%c",s.top());//输出栈顶 
					s.pop();//清除栈顶 
				}
				if(ch=='\n'||ch==EOF) break;
				printf(" "); 
			}
			else s.push(ch);//入栈 
		}
		printf("\n");
	} 
	return 0;
 } 

 

这个题本来我没想到用栈,用的翻转字符串函数,结果WA,这里说一下,翻转字符串函数strrev();反过来是world!hello


3、队列queue

先进先出

题目 HDU 1702 用栈和队列进行模拟

代码:

#include<bits/stdc++.h>
using namespace std;
int main()
{
	int t,n,temp;
	cin>>t;
	while(t--){
		string str,str1;
		//定义队列和栈 
		queue<int>Q;
		stack<int>S;
		cin>>n>>str;
		for(int i = 0;i <n;i++){
			if(str == "FIFO"){//队列 
				cin>>str1;
				if(str == "IN"){
					cin>>temp;Q.push(temp);
				}
				if(str1 == "OUT"){
					if(Q.empty())cout<<"NONE"<<endl;
					else{
						cout<<Q.front()<<endl;
						Q.pop();
					}
				}
			} 
			else{
				 cin>>str1;
				 if(str1 == "IN"){
				 	cin>>temp;S.push(temp);
				 } 
				 if(str1 == "OUT"){
				 	if(S.empty())cout<<"NONE"<<endl;
				 	else {
				 		cout<<S.top()<<endl;
				 		S.pop();
					 }
				 }
		}
	}
	return 0;
}

}

4、优先队列和priority_queue

普通队列是先进先出,有限队列是最高级先出。优先队列不是队列,是堆,底层原理是红黑树,分为大顶堆和小顶堆

题目 HDU 1873 “看病要排队”

代码:

#include<iostream>
#include<functional>
#include<queue>
#include<vector>
using namespace std;
 
//定义比较结构
struct cmp1{
    bool operator ()(int &a,int &b){
        return a>b;//最小值优先
    }
};
 
struct cmp2{
    bool operator ()(int &a,int &b){
        return a<b;//最大值优先
    }
};
 
//自定义数据结构
struct number1{
    int x;
    bool operator < (const number1 &a) const {
        return x>a.x;//最小值优先
    }
};
struct number2{
    int x;
    bool operator < (const number2 &a) const {
        return x<a.x;//最大值优先
    }
};
 
 
int a[]={14,10,56,7,83,22,36,91,3,47,72,0};
number1 num1[]={14,10,56,7,83,22,36,91,3,47,72,0};
number2 num2[]={14,10,56,7,83,22,36,91,3,47,72,0};
 
int main()
{    
    priority_queue<int>que;//采用默认优先级构造队列
 
    priority_queue<int,vector<int>,cmp1>que1;//最小值优先
    priority_queue<int,vector<int>,cmp2>que2;//最大值优先
 
    priority_queue<int,vector<int>,greater<int>  >que3;//注意“>>”会被认为错误,
    priority_queue<int,vector<int>,less<int>  >que4;最大值优先
 
    priority_queue<number1>que5; //最小优先级队列
    priority_queue<number2>que6;  //最大优先级队列
 
    int i;
    for(i=0;a[i];i++){
        que.push(a[i]);
        que1.push(a[i]);
        que2.push(a[i]);
        que3.push(a[i]);
        que4.push(a[i]);
    }
    for(i=0;num1[i].x;i++)
        que5.push(num1[i]);
    for(i=0;num2[i].x;i++)
        que6.push(num2[i]);
 
 
    printf("采用默认优先关系:/n(priority_queue<int>que;)/n");
    printf("Queue 0:/n");
    while(!que.empty()){
        printf("%3d",que.top());
        que.pop();
    }
    puts("");
    puts("");
 
    printf("采用结构体自定义优先级方式一:/n(priority_queue<int,vector<int>,cmp>que;)/n");
    printf("Queue 1:/n");
    while(!que1.empty()){
        printf("%3d",que1.top());
        que1.pop();
    }
    puts("");
    printf("Queue 2:/n");
    while(!que2.empty()){
        printf("%3d",que2.top());
        que2.pop();
    }
    puts("");
    puts("");
    printf("采用头文件/内定义优先级:/n(priority_queue<int,vector<int>,greater<int>/less<int> >que;)/n");
    printf("Queue 3:/n");
    while(!que3.empty()){
        printf("%3d",que3.top());
        que3.pop();
    }
    puts("");
    printf("Queue 4:/n");
    while(!que4.empty()){
        printf("%3d",que4.top());
        que4.pop();
    }
    puts("");
    puts("");
    printf("采用结构体自定义优先级方式二:/n(priority_queue<number>que)/n");
    printf("Queue 5:/n");
    while(!que5.empty()){
        printf("%3d",que5.top());
        que5.pop();
    }
    puts("");
    printf("Queue 6:/n");
    while(!que6.empty()){
        printf("%3d",que6.top());
        que6.pop();
    }
    puts("");
    return 0;
}

这里有一个优先队列的模板,如下:

#include<iostream>
#include<queue>
#include<string>
 
using namespace std; 
 
struct Node{
	//进行的操作 
	string str;
	//要求哪位医生诊治 
	int A;
	//当前病人的优先级 
	int B;
	//当前病人的编号,或者是说来的时间,因为要满足优先级相同时,根据先来后到诊治。 
	int time;
};
 
//自定义优先级。 
struct cmp{
	bool operator ()(const Node &a,const Node &b)
	{
		//最大值优先 
		if(a.B>b.B)
		{
			return false;
		}
		//优先级相同时,先来的优先. 
		else if(a.B==b.B)
		{
			return a.time>b.time;
		}
		else{
			return true;
		}
		
	} 
}; 
 
int main()
{
	int t;
	while(cin>>t) 
	{
		Node node;
		//定义三个医生相应的优先队列 
		priority_queue<Node,vector<Node>,cmp> doc1;
		priority_queue<Node,vector<Node>,cmp> doc2;
		priority_queue<Node,vector<Node>,cmp> doc3;
		int time = 0;
		while(t--)
		{
			cin>>node.str;
			if(node.str=="IN")
			{
				cin>>node.A>>node.B;
			}
			if(node.str=="OUT")
			{
				cin>>node.A;
			}
			if(node.str=="IN")
			{
				//根据A的值,将节点压入不同医生的队列中去 
				switch (node.A)
				{
					case 1:{
						node.time = ++time;
						doc1.push(node);
						break;
					}
					case 2:{
						node.time = ++time;
						doc2.push(node);
						break;
					}
					case 3:{
						node.time = ++time;
						doc3.push(node);
						break;
					}
				}
			}
			//如果是进行看病操作的话,进行出队列操作(恶心,用else不行,必须if判断) 
			if(node.str=="OUT"){
				switch(node.A)
				{
					case 1:{
						if(doc1.empty())
						{
							cout<<"EMPTY"<<endl;
							break;
						}
						else{
							cout<<doc1.top().time<<endl;
							doc1.pop();
							break;
						}
						
					}
					case 2:{
						if(doc2.empty())
						{
							cout<<"EMPTY"<<endl;
							break;
						}
						else{
							cout<<doc2.top().time<<endl;
							doc2.pop();
							break;
						}
					
					}
					case 3:{
						if(doc3.empty())
						{
							cout<<"EMPTY"<<endl;
							break;
						}
						else{
							cout<<doc3.top().time<<endl;
							doc3.pop();
							break;
						}
					
					}
				}
			} 
		}
	}
	return 0;
}

凡是优先队列的题,写码写到不想写


5、链表和list

list可以再任意地方删除和插入,和vector优缺点相反,注意list要使用迭代器

题目 HDU 1276“士兵队列训练问题”

代码:

#include<iostream>
#include<list>
using namespace std;
int main(){
	int N,x,i;
	list<int>a;
	list<int>::iterator it;
	int k;
	scanf("%d",&N);
	while(N--){
		scanf("%d",&x);
		a.clear();
		for(i=0;i<x;i++){
			a.push_back(i+1);//存储每个士兵的编号,索引加1 
   			}
		k=2;//第一次删除2
		while(a.size()>3){
			i=0;
			for(it=a.begin();it!=a.end();){
				if((i+1)%k == 0){//删除喊K
						   it=a.erase(it); 
				}
				else {
					 it++;
				}
				i++;
			}
			if(k==2)k=3;
			else k=2;
			
		}
		for(it=a.begin();it!=a.end();){
			printf("%d",*it);
			it++;
			if(it!=a.end())printf(" ");
			else printf("\n");
		} 
	}
	return 0;
}

6、set

集合,底层逻辑是二叉树,特点1、互异性,每个元素只允许出现一次2、不允许两个元素有相同的值3、使用empty()检查set是否为空

题目 HDU 2904“产生冠军”

代码:

#include<bits/stdc++.h>
using namespace std;
int main()
{
	set<string>A,B;//定义集合 
	string s1,s2;
	int n;
	while(cin>>n&&n)
	{
		for(int i=0;i<n;i++){
			cin>>s1>>s2;
			A.insert(s1); A.insert(s2);//把所有数据放入集合A
			B.insert(s2); 
		}
		if(A.size()-B.size()==1)
		cout<<"yes"<<endl;
		else
		cout<<"no"<<endl;
		A.clear();B.clear();
	}
	return 0;
}

7、map

映射,也需要使用迭代器

题目 HDU 2648“shopping”

代码:

#include<bits/stdc++.h>
using namespace std;
int main(){
	int n,m,p;
	map<string,int>shop;//int型字符串叫做shop
	while(cin>>n){
		string s;
		for(int i=1;i<=n;i++)
				cin>>s;
		cin>>m;
		while(m--){
			for(int i=1;i<=n;i++){
				cin>>p>>s;
				shop[s]+=p;//s作为数组下标 
			}
			int rank=1;
			//定义迭代器
			map<string,int>::iterator it;
			for(it=shop.begin();it!=shop.end();it++)
			if(it->second>shop["memony"])rank++;
			cout<<rank<<endl;
		}
		shop.clear();
	} 
	return 0;
}

 


8、sort

很常用,注意他的范围是[)包括first不包括last,在默认情况下是按照从小到大大顺序排列的

先留着,以后再来补充题目


9、next_permutation

求排列组合的函数,注意他的范围和sort一样,并且一定是一个字典的最小序列

题目 HDU 1027

代码:

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值