首页 > 其他分享 >STL学习——栈,队列,set,优先队列

STL学习——栈,队列,set,优先队列

时间:2024-07-07 10:02:09浏览次数:21  
标签:insert set 队列 元素 STL int push include

栈:

stack容器内元素的访问
​由于栈(stack)本身就是一种后进先出的数据结构。在STL中stack中只能通过top()来访问栈顶元素

栈上的基本操作
栈的基本操作包括:

函数名用途
push(x)将x入栈
top()获得栈顶元素
pop()用以弹出栈顶元素
empty()可以检测stack内是否为空,返回true为空,返回false为非空
size()返回stack内元素的个数


队列:

队列遵循先进先出,后进后出,使用上和栈stack类似

队列函数调用

函数名使用介绍
q.pop()删除queue的队头元素
q.front()返回队列的队头元素,但不删除该元素
q.back()返回队列的队尾元素,但不删除该元素
q.push(arg)将元素arg插入到队列的队尾
q.emplace(arg)将元素arg放置到队列的尾部,作用和push一样
q.size()返回队列中元素的个数
q.empty()当队列为空时返回true,否则返回false
q.swap(q1)交换q和q1中的元素,方法和stack中一样,并不会真正使用拷贝形式进行交换,只是交换底层的数据结构
swap(q,q1)非成员函数,和成员函数swap一样


set:

set 的含义是集合,它是一个有序的容器,里面的元素都是排序好的,支持插入,删除,查找等操作,就像一个集合一样。所有的操作的都是严格在logn时间之内完成,效率非常高。set 和 multiset 的区别是:set 插入的元素不能相同,但是 multiset 可以相同。其特点如下:

  1. 每个元素的键值都唯一,不允许两个元素有相同的键值。
  2. 所有元素都会根据元素的键值自动排序(默认从小到大)。
  3. set 中的元素不像 map 那样可以同时拥有实值(value)和键值(key),只能存储键,是单纯的键的集合。
  4. set 中元素的值不能直接被改变。
  5. set 支持大部分的map的操作,但是 set 不支持下标的操作,而且没有定义mapped_type类型。

set基本操作

1.set 的定义及初始化

set<Type> s						      //定义一个set容器
set<Type> s(s1)			              //定义一个set容器,并用容器s1来初始化
set<Type> s(b, e)					  //b和e分别为迭代器的开始和结束的标记
set<Type> s(s1.begin(), s1.begin()+3) //用容器s1的第0个到第2个值初始化s
set<Type> s(a, a + 5)      		      //将a数组的元素初始化vec向量,不包括a[4]
set<Type> s(&a[1], &a[4]) 			  //将a[1]~a[4]范围内的元素作为s的初始值

2.set 的基本操作

s.begin()					//返回指向第一个元素的迭代器
s.end()						//返回指向最后一个元素的迭代器
s.clear()					//清除所有元素
s.count()					//返回某个值元素的个数
s.empty()					//如果集合为空,返回true,否则返回false
s.equal_range()				//返回集合中与给定值相等的上下限的两个迭代器
s.erase()					//删除集合中的元素
s.find(k)					//返回一个指向被查找到元素的迭代器
s.insert()					//在集合中插入元素
s.lower_bound(k)			//返回一个迭代器,指向键值大于等于k的第一个元素
s.upper_bound(k)			//返回一个迭代器,指向键值大于k的第一个元素
s.max_size()				//返回集合能容纳的元素的最大限值
s.rbegin()					//返回指向集合中最后一个元素的反向迭代器
s.rend()					//返回指向集合中第一个元素的反向迭代器
s.size()					//集合中元素的数目

set用法:

1.基本用法

#include <iostream>
#include <set>
using namespace std;
int main(){
     set<int> s;
     s.insert(1);
     s.insert(2);
     s.insert(3);
     s.insert(1);
     cout<<"set的size值为 :"<<s.size()<<endl;
     cout<<"set的maxsize的值为 :"<<s.max_size()<<endl;
     cout<<"set中的第一个元素是 :"<<*s.begin()<<endl;
     s.clear();
     if(s.empty())
         cout<<"set为空"<<endl;
     cout<<"set的size值为 :"<<s.size()<<endl;
     cout<<"set的maxsize的值为 :"<<s.max_size()<<endl;
     return 0;
}

set.end()不是最后一个元素,它指向最后元素的后一位。
这样可以常用来遍历set。
实际上它效果上等同与set.size()
如果是{1, 55, 99999},那么set.size() == set.end() == 3

  1. 插入3之后虽然插入了一个1,但set中最后一个值仍然是3 。一共插入了4个数,但是集合中只有3个数并且是有序的,说明了set集合的两个特点,有序和不重复。
  2. begin() 和 end()函数是不检查set是否为空的,使用前最好使用empty()检验一下set是否为空。

2.count() 的用法

//返回某个值元素的个数
#include <iostream>
#include <set>
using namespace std;
int main(){
     set<int> s;
     s.insert(1);
     s.insert(2);
     s.insert(3);
     s.insert(1);
     cout<<"set 中 1 出现的次数是 :"<<s.count(1)<<endl;
     cout<<"set 中 4 出现的次数是 :"<<s.count(4)<<endl;
     return 0;
}

总结: count() 用来查找set中某个键值出现的次数,但因为一个键值在set只可能出现0或1次,这样就变成了判断某一键值是否在set出现过了,所以这个函数在set中并不是很实用。

3.erase() 的用法

  1. erase(iterator) :删除定位器iterator指向的值

  2. erase(first,second):删除定位器first和second之间的值

  3. erase(key_value):删除键值key_value的值

#include <iostream>
#include <set>
using namespace std;
int main(){
     set<int> s;
     set<int>::const_iterator it;
     set<int>::iterator first;
     set<int>::iterator second;
     for(int i=1; i<=10; ++i)
         s.insert(i);
     //第一种删除,删掉1
     s.erase(s.begin());
     //第二种删除,删掉2和3
     first = s.begin();
     second = s.begin();
     second++;
     second++;
     s.erase(first,second);
     //第三种删除,删掉8
     s.erase(8);
     cout<<"删除后 set 中元素是 :";
     for(it=s.begin(); it!=s.end(); ++it)
         cout<<*it<<" ";
     cout<<endl;
     return 0;
}

总结: set中的删除操作是不进行任何的错误检查的,比如定位器的是否合法等等,所以用的时候自己一定要注意。

4.find() 的用法

//返回一个指向被查找到元素的迭代器,如果没找到则返回end()
#include <iostream>
#include <set>
using namespace std;
int main(){
     int a[] = {4,5,6};
     set<int> s(a,a+3);
     set<int>::iterator it;
     if((it=s.find(4))!=s.end())
         cout<<*it<<endl;
     return 0;
}

输出结果

4

5.insert() 的用法

  1. insert(key_value):将key_value插入到set中 ,返回值是pair<set: :iterator,bool>,bool标志着插入是否成功,而iterator代表插入的位置;若key_value已经在set中,则iterator表示的key_value在set中的位置。

  2. inset(first,second);将定位器first到second之间的元素插入到set中,返回值是void.

#include <iostream>
#include <set>
using namespace std;
int main(){
     int a[] = {1,2,3};
     set<int> s;
     set<int>::iterator it;
     s.insert(a,a+3);
     for(it=s.begin(); it!=s.end(); ++it)
         cout<<*it<<" ";
     cout<<endl;
     pair<set<int>::iterator,bool> pr;
     pr=s.insert(5);
     if(pr.second)
         cout<<*pr.first<<endl;
     cout<<"插入数值之后的set中有:"<<endl;
	 for(it=s.begin(); it!=s.end(); ++it)
		cout<<*it<<" ";
	 cout<<endl;
     return 0;
}

6.lower_bound()、upper_bound() 的用法

  1. lower_bound(key_value) :返回第一个大于等于key_value的定位器

  2. upper_bound(key_value):返回第一个大于key_value的定位器

#include <iostream>
#include <set>
using namespace std;
int main(){
     set<int> s;
     s.insert(1);
     s.insert(3);
     s.insert(4);
     s.insert(6);
     cout<<*s.lower_bound(1)<<endl;
     cout<<*s.lower_bound(2)<<endl;
     cout<<*s.upper_bound(3)<<endl;
     return 0;
}

输出结果:

1
3
4

7.equal_range() 的用法

equal_range():返回一对定位器,分别表示第一个大于等于给定关键值的元素和第一个大于给定关键值的元素,这个返回值是一个pair类型。如果这一对定位器中哪个返回失败,就会等于end()的值。

#include <iostream>
#include <set>
#include <algorithm>
using namespace std;
int main(){
	set<int> s;
	set<int>::iterator it;
	for(int i=1; i<=5; ++i)
		s.insert(i); //向set中加入数据
	for(it=s.begin(); it!=s.end(); ++it)
		cout<<*it<<" ";  //输出set中的数据
	cout<<endl;
	pair<set<int>::const_iterator,set<int>::const_iterator> pr;
	pr=s.equal_range(3);
	cout<<"第一个大于等于3的数是:"<<*pr.first<<endl;
	cout<<"第一个大于3的数是: "<<*pr.second<<endl;
	return 0;
}

8.自定义比较函数
(1). 元素不是结构体:

 //自定义比较函数myComp,重载“()”操作符
struct myComp{
	bool operator()(const your_type &a,const your_type &b){
		return a.data > b.data;
	}
}
set<int,myComp>s;
set<int,myComp>::iterator it;

(2). 元素是结构体:

//可以直接将比较函数写在结构体内
struct Info{
	string name;
	float score;
	//重载“<”操作符,自定义排序规则
	bool operator < (const Info &a) const{
		//按score从大到小排列
		return a.score<score;
	}
}
 
set<Info> s;
set<Info>::iterator it;


优先队列:

和queue不同的就在于我们可以自定义其中数据的优先级, 让优先级高的排在队列前面,优先出队

优先队列具有队列的所有特性,包括基本操作,只是在这基础上添加了内部的一个排序,它本质是一个堆实现的

和队列基本操作相同:

· top 访问队头元素
· empty 队列是否为空
· size 返回队列内元素个数
· push 插入元素到队尾 (并排序)
· emplace 原地构造一个元素并插入队列
· pop 弹出队头元素
· swap 交换内容

定义:priority_queue<Type, Container, Functional>
Type 就是数据类型
Container 就是容器类型(Container必须是用数组实现的容器,比如vector,deque等等,但不能用 list。STL里面默认用的是vector)
Functional 就是比较的方式,当需要用自定义的数据类型时才需要传入这三个参数,使用基本数据类型时,只需要传入数据类型,默认是大顶堆

一般是:

//升序队列
priority_queue <int,vector<int>,greater<int> > q;
//降序队列
priority_queue <int,vector<int>,less<int> >q;

//greater和less是std实现的两个仿函数
//(就是使一个类的使用看上去像一个函数。其实现就是类中实现一个operator(),这个类就有了类似函数的行为,就是一个仿函数类了)

基本类型例子:

#include<iostream>
#include <queue>
using namespace std;
int main() 
{
    //对于基础类型 默认是大顶堆
    priority_queue<int> a; 
    //等同于 priority_queue<int, vector<int>, less<int> > a;
    
  
    priority_queue<int, vector<int>, greater<int> > c;  //这样就是小顶堆
    priority_queue<string> b;

    for (int i = 0; i < 5; i++) 
    {
        a.push(i);
        c.push(i);
    }
    while (!a.empty()) 
    {
        cout << a.top() << ' ';
        a.pop();
    } 
    cout << endl;

    while (!c.empty()) 
    {
        cout << c.top() << ' ';
        c.pop();
    }
    cout << endl;

    b.push("abc");
    b.push("abcd");
    b.push("cbd");
    while (!b.empty()) 
    {
        cout << b.top() << ' ';
        b.pop();
    } 
    cout << endl;
    return 0;
}

输出:

4 3 2 1 0
0 1 2 3 4
cbd abcd abc

pari的比较,先比较第一个元素,第一个相等比较第二个

#include <iostream>
#include <queue>
#include <vector>
using namespace std;
int main() 
{
    priority_queue<pair<int, int> > a;
    pair<int, int> b(1, 2);
    pair<int, int> c(1, 3);
    pair<int, int> d(2, 5);
    a.push(d);
    a.push(c);
    a.push(b);
    while (!a.empty()) 
    {
        cout << a.top().first << ' ' << a.top().second << '\n';
        a.pop();
    }
}

输出:

2 5
1 3
1 2

对于自定义类型

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

//方法1
struct tmp1 //运算符重载<
{
    int x;
    tmp1(int a) {x = a;}
    bool operator<(const tmp1& a) const
    {
        return x < a.x; //大顶堆
    }
};

//方法2
struct tmp2 //重写仿函数
{
    bool operator() (tmp1 a, tmp1 b) 
    {
        return a.x < b.x; //大顶堆
    }
};

int main() 
{
    tmp1 a(1);
    tmp1 b(2);
    tmp1 c(3);
    priority_queue<tmp1> d;
    d.push(b);
    d.push(c);
    d.push(a);
    while (!d.empty()) 
    {
        cout << d.top().x << '\n';
        d.pop();
    }
    cout << endl;

    priority_queue<tmp1, vector<tmp1>, tmp2> f;
    f.push(c);
    f.push(b);
    f.push(a);
    while (!f.empty()) 
    {
        cout << f.top().x << '\n';
        f.pop();
    }
}

输出:

3
2
1

3
2
1

L2-2 含茶量
分数 25
作者 陈越
单位 浙江大学

PTA | 程序设计类实验辅助教学平台

#include<bits/stdc++.h>
#include<iostream>
#include<vector>
#include<algorithm>
#include<set>
#include<stack>
#include<string>
#include<queue>
#include<cctype>
#include<map>
#include<unordered_map>
using namespace std;
#define int long long
#define endl '\n'
#define inf 0x3f3f3f3f
struct ide{
	string id;
	string s;
};
struct cmp
{
	bool operator()(const pair<string, int>& p1, const pair<string, int>& p2)
	{
		if (p1.second == p2.second) return p1.first < p2.first;
		return p1.second > p2.second;
	}
};

signed main()
{
	ios::sync_with_stdio(false);cin.tie(nullptr);cout.tie(nullptr);
	int n;
	cin>>n;
	priority_queue<pair<string,int>,vector<pair<string,int>>,cmp>p;
	unordered_map<string,int>u;
	for(int i = 0;i <n; i++)
	{
		string s1,s2;
		cin>>s1;
		cin.ignore();
		getline(cin,s2);
		for(int j=0;j<s2.size();j++)
		{
			if(s2[j]>='A'&&s2[j]<= 'Z')
			{
				s2[j]+=32;
			}
		}
		string temp=s2;
		int cnt=0;
		int index=0;
		int n=s2.size();
		while(index!=-1)
		{
			index=temp.find("chatgpt");
			if(index!=-1)
			{
				cnt++;
				temp=temp.substr(index+1);
			}
		}
		u[s1]+=cnt;
	}
	for(auto&e:u)
	{
		p.push(e);
		if(p.size()>3)
			p.pop();	
	}
	vector<pair<string,int>>vp;
	while(p.size()>0)
	{
		pair<string,int>tmp=p.top();
		p.pop();
		vp.push_back(tmp);
	}
	while(vp.size()>0)
	{
		if(vp.back().second>0)
		{
			cout<<vp.back().first<<" "<<vp.back().second<<endl;
		}
		vp.pop_back();
	}
	return 0;
}

标签:insert,set,队列,元素,STL,int,push,include
From: https://blog.csdn.net/miaojiachun/article/details/135117279

相关文章

  • mORMot虚拟数据集--TOrmTableDataSet
    如何快速显示OrmTable--可以使用TOrmTableDataSet这是mormot.db.rad.ui.orm的主要功能type///只读虚拟TDataSet,能够访问TOrmTableTOrmTableDataSet=class(TVirtualDataSet)protectedfTable:TOrmTable;//关联的TOrmTable实例{$ifndefUNICODE}//如......
  • [Redis]ZSet
    通过value查score在Redis的有序集合(zset)中,通过成员(member)获取其对应的分数(score)的复杂度是O(logN),其中N是有序集合中的元素数量。这是因为Redis使用跳跃表(skiplist)和哈希表(hashtable)的组合来实现有序集合。跳跃表用于按顺序存储元素,以便高效地按分数排序和查找范围,而哈......
  • Redis的zset的zrem命令可以做到O(1)吗?
    事情是这样的,当我用zrem命令去移除value的时候,我知道他之前会做的几个步骤1、查找这个value对应的score(通过zset中的dict)2、根据这个score查找到跳表中的节点3、删除这个节点我就想了一下为什么dict为什么要保存score呢?如果保存的是跳表中的节点,那么不就可以做到删除O(1)......
  • 【数据结构】栈和队列
    文章目录1.栈1.1栈的概念及结构1.2栈的实现2.队列2.1队列的概念及结构2.2队列的实现3.栈和队列面试题4.概念选择题1.栈1.1栈的概念及结构栈:一种特殊的线性表,其只允许在固定的一端进行插入和删除元素操作。进行数据插入和删除操作的一端称为栈顶,另一端称为栈......
  • 在 Windows 操作系统中,HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tc
    在Windows操作系统中,HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters下的两个重要参数控制着TCP/IP协议栈的行为。这些参数可以通过注册表来配置,影响网络连接和端口资源的管理。1.MaxUserPort路径: HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSe......
  • 在注册表路径 HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Control\Session Manager
    在注册表路径HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Control\SessionManager\MemoryManagement下的LargeSystemCache键控制着操作系统如何管理系统缓存和内存分配,不同的数值对应不同的行为和设置。LargeSystemCache参数详解0(默认值):效果:系统将系统缓存减少到最......
  • 在注册表路径 HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Man
    在注册表路径HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SessionManager\MemoryManagement下的DisablePagingExecutive键控制着操作系统内核数据是否允许分页到页面文件中。这个设置对系统性能和稳定性有重要影响,特别是在高负载和内存紧张的情况下。DisablePagi......
  • Pinia 实用教程【Vue3 状态管理】状态持久化 pinia-plugin-persistedstate,异步Action,s
    什么是状态管理?全局状态Store(如Pinia)是一个保存状态和业务逻辑的实体,与组件树没有绑定,有点像一个永远存在的组件,每个组件都可以读取和写入它。三大核心概念state属性——相当于组件中的datagetter计算属性——相当于组件中的computedaction操作属性的......
  • PostgreSQL的系统视图pg_file_settings和pg_settings的区别
    PostgreSQL的系统视图pg_file_settings和pg_settings的区别pg_file_settings和pg_settings是PostgreSQL中两个相关的系统视图,它们用于查看和管理数据库的配置设置。这两个视图提供了不同层次的配置信息,适用于不同的管理和调试需求。以下是它们的区别和特点:pg_file_se......
  • .NET控制台读取appsettings.json,配置日志
    需要安装nuget包Microsoft.Extensions.Configuration 、Microsoft.Extensions.Configuration.FileExtensions、Microsoft.Extensions.Configuration.Json、NLogusingNLog;usingNLog.Config;usingMicrosoft.Extensions.Configuration;namespaceConsoleApp2{int......