【PAT笔记】C++常用工具使用手册

1.set 

set的结构体重载以及内部成员访问。

struct node {
	int a,b;
	bool friend operator <(node n1,node n2) {
		return n1.a < n2.a;
	}
};
set<node>nset;
int main() {

	for (int i = 0; i < 10; i++) 
		nset.insert({100-i,i});
	for (auto it = nset.begin(); it != nset.end(); it++)
		cout << it->a << " " << it->b << endl;
		return 0;
}

对于结构体的成员访问需要使用 it->a ,但是对于set<int>这样的容器元素访问,就需要*it。

set<int>iset;
int main() {
	for (int i = 0; i < 10; i++)
		iset.insert(20 - i);
	iset.erase(15);    //删除元素
	if (iset.find(15) == iset.end())cout << "15 is deleted!" << endl;    //查找元素
	for (auto it = iset.begin(); it != iset.end(); it++)
		cout << *it << endl;
		return 0;
}

什么时候用得到set以及其重载:

(1)含负数的不重复统计时使用,如果数据较小且全部为正数时,直接使用数组统计。

(2)结构体查找时使用,经测试,1e6的数据量查找一次几乎不花时间。P.S.结构体查找时lower_bound不可用。

 

注意:(1)set<int>插入1e5次就需要1.4秒,必然超时,插入1e4次需要138毫秒,最多插入1e4次,而且是单int变量,可见适用范围并不广。

 

2.lower_bound和upper_bound

用于二分查找,可以查找结构体和元素,可以用普通数组也可以使用vector容器。

头文件:#include <algorithm> 考场上直接一个 #include<bits/stdc++.h>

基本使用格式:

(1) : int pos = lower_bound(begin , end ,value) - begin ;

     得到大于等于value的第一个元素的数组下标

(2) : int *pos = lower_bound(begin , end ,value) ;

    返回相应元素的指针,可以使用 cout<<*pos ;来输出对应元素

(3) : int *pos = lower_bound(begin , end ,value,greater<type>()) ;

    如果数组是从大到小排的,返回第一个小于等于value的数字的一种重载。

(4) : int pos = lower_bound(vector.begin() , vector.end(),value) - vector.begin() ;

    可以使用vector容器进行操作,不过这样就需要从头至尾的查找了,数组后面有空的话不可用。

 重载结构体的使用格式:

结构体的建立:

struct  node{
	int year, month, day;
	bool friend operator <(node a,node b){
		if (a.year != b.year)return a.year < b.year;
		else if (a.month != b.month)return a.month < b.month;
		else return a.day < b.day;
	}
};
vector<node>epoch(100);

结构体初始化及排序:

for (int i = 0; i < 100; i++) {
		epoch[i].year = randomInt(1000, 2020);
		epoch[i].month = randomInt(1, 12);
		epoch[i].day = randomInt(1, 30);
		era[i] = epoch[i];
	}

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

打印:

for (int i = 0; i < 100; i++) {
		printf("(%d) %d 年 %d 月 %d 日\n",i, epoch[i].year, epoch[i].month, epoch[i].day);
	}

开始查找:

node value = { 1946,2,14 };
	int pos = lower_bound(epoch.begin(), epoch.end(),value) - epoch.begin();

cout << "pos: " << pos <<"   "<< endl;

注意:(1)已经有序的数组,可以是升序或者降序

           (2)如果找不到目标,则返回end地址。

           (3)upper_bound使用方法同理。

           (4)1e7的查找时间依然在10ms一下,可见是非常快的

 

3.map 和unordered_map

用于键值和值之间的映射关系,以红黑树实现,速度较慢。

头文件:#include<map>     #include<unordered_map>

对于一般的 “数字——>任意” 这样的映射关系数组是最佳映射方式,时间为O(1)

使用场景:(1)键值含有负数,不能直接使用数组下标映射的。

                  (2)字符串作为键值的情景。

                  (3)用于统计非数字键值个数。

基本使用格式:

声明对象和迭代器
map<string, string>testList;
map<string, string>::iterator it;
map<string, string>::reverse_iterator rit;

unordered_map<string, string>testList2;
unordered_map<string, string>::iterator it2;

正向遍历

for (it = testList.begin(); it != testList.end(); it++)
	cout << it->first << " : " << it->second << endl;

逆向遍历
for (rit = testList.rbegin(); rit != testList.rend(); rit++)
	cout << rit->first << " : " << rit->second << endl;

对内部成员的访问:

(1)使用迭代器it进行访问,可以对it->second进行赋值和取值,但是对it->first只能进行取值。

(2)可以使用数组形式进行访问,也只是访问testList[keyValue],可以取值也可以赋值,同时可以覆盖插入。

(3)用作统计作用时,如果 testList[keyValue] 为空或者为0,则keyValue这个元素未出现。

(4)insert进行插入时,如果键值已存在是无法进行插入的,也无法覆盖原值,等于啥也没做。

testList.insert(pair<string, string>("keyValue", "secondValue"));

注意:(1) map:1e4的数据插入一遍就需要480ms左右,unordered_map会快一点点,经测试在360ms左右。

           (2)遍历速度还是比较快的,1e5 的数据180ms左右。

           (3)使用unordered_map时,其内部并不会保持其插入时的顺序,而是根据建树需要给出一个他的顺序。

 

4.priority_queue 

非常好用的数据结构,用堆实现,稳定性强。

头文件:#include<queue>   #include<vector>     #include<functional>

最后一个头文件用于great<int> ,将堆变为小顶堆。

 

使用场景:(1)只关注极值的操作过程,比如外部排序每次排出去一个最小的。

                  (2)哈夫曼编码类问题。

                  (3)一些队列模拟,比如银行队列,进程调度之类的模拟。

基本是用格式:

默认大顶堆:
priority_queue<int>prique;
	
小顶堆使用:
priority_queue<int, vector<int>, greater<int> > qi2;

push操作:
for (int i = 0; i < 100; i++) qi2.push(randomInt(1, 1000));

循环pop:
while (!qi2.empty()){ cout<< qi2.top()<<endl ; qi2.pop();}

结构体重载使用priority_queue:

struct  node{
	int year, month, day;
	bool friend operator <(node a,node b){
		if (a.year != b.year)return a.year < b.year;
		else if (a.month != b.month)return a.month < b.month;
		else return a.day < b.day;
	}
};

priority_queue<node>epoch;

for (int i = 0; i < 1000; i++) 	
epoch.push({randomInt(1000,2020),randomInt(1,12) ,randomInt(1,30)});

while (!epoch.empty()){
	node tp = epoch.top();
	epoch.pop();
	cout<< tp.year<<"年"<<tp.month<<"月"<<tp.day<<"日"<<endl ;
}

注意:(1)push操作耗时:1e5的数据量在500ms左右。

           (2)pop操作:1e3的耗时在30ms左右,但是到1e4的耗时就达到2秒,所以pop操作不能用太多。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值