黑马c++ STL部分 笔记(8) set/ multiset 容器

简介: 黑马c++ STL部分 笔记(8) set/ multiset 容器

简介

所有元素都会在插入时自动被排序

本质

set/multiset属于关联式容器,底层结构是用二叉树实现。

set和multiset区别

set允许容器中有重复的元素

multiset允许容器中有重复的元素


1.set构造和赋值

// set构造和赋值
/*
构造:
set<T> st; //默认构造函数:
set(const set &st); //拷贝构造函数
赋值:
set& operator=(const set &st); //重载等号操作符
*/
#include <bits/stdc++.h>
using namespace std;
void printset(set<int> &s)
{
  for (set<int>::iterator it = s.begin(); it != s.end(); it++)
  {
    cout << *it << " ";
  }
  cout << endl;
}
 
void test01()
{
  set<int> s1;
  s1.insert(10); // 插入数据只有insert方式
  s1.insert(30);
  s1.insert(40);
  s1.insert(20);
  s1.insert(30);
  // set里的元素自动被排序,不允许插入重复的值
  printset(s1); // 10 20 30 40
  // 拷贝构造
  set<int> s2(s1);
  printset(s2); // 10 20 30 40
  // 赋值
  set<int> s3;
  s3 = s2;
  printset(s3); // 10 20 30 40
}
int main()
{
  test01();
}
/*
总结:
set容器插入数据时用insert
set容器插入数据的数据会自动排序
*/


2. set大小和交换

// set大小和交换
/*不支持resize
size(); //返回容器中元素的数目
empty(); //判断容器是否为空
swap(st); //交换两个集合容器
*/
#include <bits/stdc++.h>
using namespace std;
void printset(set<int> &s)
{
  for (set<int>::iterator it = s.begin(); it != s.end(); it++)
  {
    cout << *it << " ";
  }
  cout << endl;
}
 
void test01()
{
  set<int> s1;
  s1.insert(10);
  s1.insert(30);
  s1.insert(40);
  s1.insert(20);
  s1.insert(30);
 
  printset(s1); // 10 20 30 40
  if (s1.empty())
  {
    cout << "s1为空" << endl;
  }
  else
  {
    cout << "s1为不空" << endl;
    cout << s1.size() << endl; // 4
  }
  set<int> s2;
  s2.insert(10);
  printset(s2); // 10
  s1.swap(s2);
  printset(s1); // 10
  printset(s2); // 10 20 30 40
}
int main()
{
  test01();
}
/*
总结:
统计大小 — size
判断是否为空 — empty
交换容器 — swap
*/


3.set插入和删除

// set插入和删除
/*
insert(elem); //在容器中插入元素。
clear(); //清除所有元素
erase(pos); //删除pos'迭代器'所指的元素,返回下一个元素的迭代器。
erase(beg, end); //删除区间[beg,end)的所有元素 ,返回下一个元素的迭代器。
erase(elem); //删除容器中'值'为elem的元素。(类似remove)
*/
#include <bits/stdc++.h>
using namespace std;
void printset(set<int> &s)
{
  for (set<int>::iterator it = s.begin(); it != s.end(); it++)
  {
    cout << *it << " ";
  }
  cout << endl;
}
 
void test01()
{
  set<int> s1;
  // 插入
  s1.insert(30);
  s1.insert(10);
  s1.insert(40);
  s1.insert(20);
  s1.insert(30);
  printset(s1); // 10 20 30 40
  // 删除迭代器位置
  s1.erase(s1.begin());
  printset(s1); // 20 30 40
  // 删除元素
  s1.erase(40);
  printset(s1); // 20 30
  // 清空
  s1.clear();
  printset(s1);
}
int main()
{
  test01();
}
/*
总结:
插入 — insert
删除 — erase
清空 — clear
*/


4.set查找和统计

// set查找和统计
/*
find(key); //查找key是否存在,若存在,返回该键的元素的'迭代器';若不存在,返回'set.end()';
count(key); //统计key的'元素'个数  set中返回0/1 multiset为0/>0的值
*/
#include <bits/stdc++.h>
using namespace std;
void printset(set<int> &s)
{
  for (set<int>::iterator it = s.begin(); it != s.end(); it++)
  {
    cout << *it << " ";
  }
  cout << endl;
}
 
void test01()
{
  set<int> s1;
  // 插入
  s1.insert(30);
  s1.insert(10);
  s1.insert(40);
  s1.insert(20);
  s1.insert(30);
  printset(s1); // 10 20 30 40
  // 查找
  set<int>::iterator pos = s1.find(40);
  if (pos != s1.end())
  {
    cout << "找到元素:" << *pos << endl; // 找到元素:40
  }
  else
  {
    cout << "未找到元素:" << endl;
  }
  // 统计
  int num = s1.count(30); // 统计30的个数
  cout << num << endl;    // 1
}
int main()
{
  test01();
}
/*
总结:
查找 — find (返回的是迭代器)
统计 — count (对于set,结果为0或者1)
*/


5.set和multiset区别

// set和multiset区别
/*
区别:
set不可以插入重复数据,而multiset可以
set插入数据的同时会返回插入结果,表示插入是否成功
multiset不会检测数据,因此可以插入重复数据
*/
#include <bits/stdc++.h>
using namespace std;
void test01()
{
  set<int> s;
  // set插入
  pair<set<int>::iterator, bool> ret = s.insert(10);
  if (ret.second)
  {
    cout << "第一次插入成功" << endl; // √
  }
  else
  {
    cout << "第一次插入失败" << endl; // ×
  }
  // set重复插入
  ret = s.insert(10);
  if (ret.second)
  {
    cout << "第二次插入成功" << endl; // ×
  }
  else
  {
    cout << "第二次插入失败" << endl; // √
  }
  multiset<int> s2;
  // multiset插入
  s2.insert(10);
  // multiset重复插入
  s2.insert(10);
  for (multiset<int>::iterator it = s2.begin(); it != s2.end(); it++)
  {
    cout << *it << " "; // 10 10
  }
}
int main()
{
  test01();
}
/*
总结:
如果不允许插入重复数据可以利用set
如果需要插入重复数据利用multiset
*/


6. pair对组创建

// pair对组创建
/*
两种创建方式:
pair<type, type> p ( value1, value2 );
pair<type, type> p = make_pair( value1, value2 );
*/
#include <bits/stdc++.h>
using namespace std;
void test01()
{
  pair<string, int> p("Tom", 20);
  cout << p.first << " " << p.second << endl; // Tom 20
  pair<string, int> p2 = make_pair("Jerry", 15);
  cout << p2.first << " " << p2.second << endl; // Jerry 15
}
int main()
{
  test01();
}
/*
总结:
两种方式都可以创建对组,记住一种即可
*/


7.1  set容器排序

示例一 set存放内置数据类型

//  set容器排序
/*
学习目标:
set容器默认排序规则为从小到大,掌握如何改变排序规则
主要技术点:
利用仿函数,可以改变排序规则
*/
// 示例一 set存放内置数据类型
#include <bits/stdc++.h>
using namespace std;
class cmp // 仿函数(类)
{
public:
  bool operator()(int v1, int v2)
  {
    return v1 > v2;
  }
};
void test01()
{
  // 升序
  set<int> s1;
  s1.insert(10);
  s1.insert(30);
  s1.insert(20);
  s1.insert(50);
  s1.insert(40);
  for (set<int>::iterator it = s1.begin(); it != s1.end(); it++)
  {
    cout << *it << " "; // 10 20 30 40 50
  }
  cout << endl;
  // 降序,在创建容器时就指定排序规则
  set<int, cmp> s2;
  s2.insert(10);
  s2.insert(30);
  s2.insert(20);
  s2.insert(50);
  s2.insert(40);
  for (set<int, cmp>::iterator it = s2.begin(); it != s2.end(); it++)
  {
    cout << *it << " "; // 50 40 30 20 10
  }
  cout << endl;
}
int main()
{
  test01();
}
/*
总结:
对于自定义数据类型,set必须指定排序规则才可以插入数据
*/


7.2  set容器排序

示例二 set存放自定义数据类型

//  set容器排序
// 示例二 set存放自定义数据类型
#include <bits/stdc++.h>
using namespace std;
 
class person
{
public:
  person(string name, int age)
  {
    this->name = name;
    this->age = age;
  }
  string name;
  int age;
};
class cmp
{
public:
  bool operator()(person p1, person p2)
  {
    // 按年龄降序
    return p1.age > p2.age;
  }
};
void test01()
{
  /// 自定义的类型 都会指定排序类型
  set<person, cmp> s;
  person s1("刘备", 24);
  person s2("关羽", 28);
  person s3("张飞", 25);
  person s4("赵云", 21);
  s.insert(s1);
  s.insert(s2);
  s.insert(s3);
  s.insert(s4);
  for (set<person, cmp>::iterator it = s.begin(); it != s.end(); it++)
  {
    cout << (*it).name << " " << (*it).age;
    /*
   关羽 28
   张飞 25
   刘备 24
   赵云 21
   */
    cout << endl;
  }
}
int main()
{
  test01();
}
/*
总结:
对于自定义数据类型,set必须指定排序规则才可以插入数据
*/


相关文章
|
2月前
|
存储 C++ 容器
【C++】map、set基本用法
本文介绍了C++ STL中的`map`和`set`两种关联容器。`map`用于存储键值对,每个键唯一;而`set`存储唯一元素,不包含值。两者均基于红黑树实现,支持高效的查找、插入和删除操作。文中详细列举了它们的构造方法、迭代器、容量检查、元素修改等常用接口,并简要对比了`map`与`set`的主要差异。此外,还介绍了允许重复元素的`multiset`和`multimap`。
45 3
【C++】map、set基本用法
|
2月前
|
存储 算法 C++
【C++】unordered_map(set)
C++中的`unordered`容器(如`std::unordered_set`、`std::unordered_map`)基于哈希表实现,提供高效的查找、插入和删除操作。哈希表通过哈希函数将元素映射到特定的“桶”中,每个桶可存储一个或多个元素,以处理哈希冲突。主要组成部分包括哈希表、哈希函数、冲突处理机制、负载因子和再散列,以及迭代器。哈希函数用于计算元素的哈希值,冲突通过开链法解决,负载因子控制哈希表的扩展。迭代器支持遍历容器中的元素。`unordered_map`和`unordered_set`的插入、查找和删除操作在理想情况下时间复杂度为O(1),但在冲突较多时可能退化为O(n)。
32 5
|
2月前
|
存储 C++ 容器
【C++】set模拟实现
C++中的`set`是STL提供的一种关联容器,用于存储唯一元素并自动按特定顺序(默认升序)排序。其内部通过红黑树实现,保证了高效的插入、删除和查找操作,时间复杂度均为O(log n)。`set`支持迭代器遍历,提供了良好的数据访问接口。
44 3
|
3月前
|
Kubernetes Cloud Native 流计算
Flink-12 Flink Java 3分钟上手 Kubernetes云原生下的Flink集群 Rancher Stateful Set yaml详细 扩容缩容部署 Docker容器编排
Flink-12 Flink Java 3分钟上手 Kubernetes云原生下的Flink集群 Rancher Stateful Set yaml详细 扩容缩容部署 Docker容器编排
113 3
|
3月前
|
并行计算 Python
Python错误笔记(一):CUDA initialization: CUDA unknown error - this may be due to an incorrectly set up env
这篇文章讨论了CUDA初始化时出现的未知错误及其解决方案,包括重启系统和安装nvidia-modprobe。
395 0
|
5月前
|
C++ 容器
【C/C++笔记】迭代器
【C/C++笔记】迭代器
49 1
|
5月前
|
应用服务中间件 API 网络安全
运维笔记:宿主机转发实现多容器复用CA证书
运维笔记:宿主机转发实现多容器复用CA证书
53 4
|
5月前
|
存储 安全 程序员
【C/C++笔记】迭代器范围
【C/C++笔记】迭代器范围
80 0
|
6月前
|
C++ Windows
FFmpeg开发笔记(三十九)给Visual Studio的C++工程集成FFmpeg
在Windows上使用Visual Studio 2022进行FFmpeg和SDL2集成开发,首先安装FFmpeg至E:\msys64\usr\local\ffmpeg,然后新建C++控制台项目。在项目属性中,添加FFmpeg和SDL2的头文件及库文件目录。接着配置链接器的附加依赖项,包括多个FFmpeg及SDL2的lib文件。在代码中引入FFmpeg的`av_log`函数输出"Hello World",编译并运行,若看到"Hello World",即表示集成成功。详细步骤可参考《FFmpeg开发实战:从零基础到短视频上线》。
290 0
FFmpeg开发笔记(三十九)给Visual Studio的C++工程集成FFmpeg
|
6月前
|
存储 C++ 容器
【C++】开散列实现unordered_map与unordered_set的封装
【C++】开散列实现unordered_map与unordered_set的封装
66 0

热门文章

最新文章