黑马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必须指定排序规则才可以插入数据
*/


相关文章
|
3天前
|
编译器 C++
《Effective C++ 改善程序与设计的55个具体做法》 第一章 笔记
《Effective C++ 改善程序与设计的55个具体做法》 第一章 笔记
|
4天前
|
算法 C++
算法笔记:递归(c++实现)
算法笔记:递归(c++实现)
|
13天前
|
存储 算法 编译器
8.STL中Vector容器的常见操作(附习题)
8.STL中Vector容器的常见操作(附习题)
|
19小时前
|
算法 前端开发 Linux
【常用技巧】C++ STL容器操作:6种常用场景算法
STL在Linux C++中使用的非常普遍,掌握并合适的使用各种容器至关重要!
26 10
|
3天前
|
编译器 C++
《Effective C++ 改善程序与设计的55个具体做法》 第二章 构造/析构/赋值运算 笔记
《Effective C++ 改善程序与设计的55个具体做法》 第二章 构造/析构/赋值运算 笔记
|
3天前
|
存储 小程序 程序员
Essential C++ 第1章 C++编程基础 (笔记)
Essential C++ 第1章 C++编程基础 (笔记)
|
3天前
|
算法 C语言 C++
面向考试编程C++笔记
面向考试编程C++笔记
|
23小时前
|
监控 Java 数据安全/隐私保护
性能监控之 JMX 监控 Docker 容器中的 Java 应用
【6月更文挑战9天】性能监控之 JMX 监控 Docker 容器中的 Java 应用
13 1
|
1天前
|
NoSQL 关系型数据库 Redis
Docker的通俗理解和通过宿主机端口访问Redis容器的实例
本文目标:引导初学者入门Docker,理解镜像、容器和宿主机概念,学习常用Docker命令,特别是如何创建并从Redis容器通过宿主机端口访问。 关键点: - Docker核心:镜像(类)、容器(实例)、宿主机(运行环境)。 - `docker pull` 拉取镜像,如 `redis:3.0`。 - `docker run -d --name` 后台运行容器,如 `my-redis`。 - `-p` 参数做端口映射,如 `6379:6379`。 - `docker exec -it` 交互式进入容器,如 `bash` 或执行命令。
|
5天前
|
运维 Ubuntu Docker
深入理解容器化技术:Docker的应用与实践
在这个数字化转型迅速推进的时代,容器化技术为软件开发和部署提供了新的路径。本文将深入探讨Docker技术的基本原理、应用场景以及实际操作,旨在帮助读者全面理解并掌握这一关键技术。
30 2

热门文章

最新文章