数据结构系列(一) 集合与其基本操作

集合与其基本操作

数据结构系列第一章:集合与其基本操作



前言

常说:一个程序 = 算法 + 数据结构
数据结构的重要性可见一斑
这个系列将讲解一些较为重要的数据结构

一、集合

集合作为我们的关联容器的一种,它的优势也有很多
1.集合内无重复:一个集合内,没有相同的数据,依照这个特点,我们可以使用集合来去重,查重
2.集合内有序:一个集合,它的数据是有序的,它支持结构体,可以使用greater<>排序,也可以运算符重载,下文将有所提及

二、集合的使用(c++ STL)

在c++标准模板库内,有集合 set 这个容器
这里就用STL给大家演示
我们可以用它来简化代码

1.头文件

使用集合时,首先要包含这样的一个头文件

#include <set>

2.基本操作

创建集合时,常用的两种创建方法:
1.建立空集(即没有元素在集合内)

#include <algorithm>
#include <cstdio>
#include <iostream>
#include <set> //必须包含这个头文件
using namespace std;

int main()
{
	set <int> set_1; //定义一个空集

	return 0;
}

2.使用数组建立,建立时注意左闭右开

#include <algorithm>
#include <cstdio>
#include <iostream>
#include <set> //必须包含这个头文件
using namespace std;

int main()
{
	int a[] = {5 , 2 , 3 , 1 , 6 , 2 , 4};
	set <int> set_2(a , a + 7); //使用 a 数组定义集合,定义时注意左闭右开

	return 0;
}

集合的插入
1.直接插入数据(在输入时处理可以使用)

#include <algorithm>
#include <cstdio>
#include <iostream>
#include <set> //必须包含这个头文件
using namespace std;

int main()
{
	set <int> set_1;
	set_1.insert(4); //在集合中放入 4 这个元素

	return 0;
}

2.在指定位置插入数据
注意,这并不会改变集合原来的排序顺序,因为在插入后集合是会更新的

#include <algorithm>
#include <cstdio>
#include <iostream>
#include <set> //必须包含这个头文件
using namespace std;

int main()
{
	set <int> set_1;

	set_1.insert(set_1.begin() , 4); //例:在集合的头部插入 4 ,意义不大,最终还是会进行排序

    return 0;
}

集合的删除
这里为大家提供两种操作方法

1.删除指定元素
注意呦,是删除指定的元素,而不是删除这一位上的元素
还是那句话,除首尾外,集合无法使用随机访问器,必须使用迭代器进行访问,具体可以参照输出部分

#include <algorithm>
#include <cstdio>
#include <iostream>
#include <set> //必须包含这个头文件
using namespace std;

int main()
{
	int a[] = {5 , 2 , 3 , 1 , 6 , 2 , 4};
	set <int> set_1(a , a + 7); //使用 a 数组定义集合,定义时注意左闭右开

	set_1.erase(set_1.begin()); //删除集合的第一个元素
	set_1.erase(5); //删除 5 这个元素,不是删除第五个元素

	return 0;
}

2.删除一个区间内的元素(一般在清空集合时使用)

#include <algorithm>
#include <cstdio>
#include <iostream>
#include <set> //必须包含这个头文件
using namespace std;

int main()
{
	int a[] = {5 , 2 , 3 , 1 , 6 , 2 , 4};
	set <int> set_1(a , a + 7); //使用 a 数组定义集合,定义时注意左闭右开

	set_1.erase(set_1.begin() , set_1.end()); //删除一个区间的元素

	return 0;
}

集合的输出

集合无法使用随机访问器,必须使用迭代器进行访问

#include <algorithm>
#include <cstdio>
#include <iostream>
#include <set> //必须包含这个头文件
using namespace std;

int main()
{
	int a[] = {5 , 2 , 3 , 1 , 6 , 2 , 4};
	set <int> set_1(a , a + 7); //使用 a 数组定义集合,定义时注意左闭右开
	/*
    我们会发现 a 数组并不是排序后的,还有重复
    打印出集合来看看
	*/
	
	set <int> :: iterator it; //集合无法随机访问,必须使用迭代器
	for(it = set_1.begin() ; it != set_1.end() ; it++)//这里小心踩个坑:结束条件应为 !=  不是 < 呦,集合是不能随机访问的
	{
		printf("%d\n" , *it);//打印数据时迭代器要返回指针
	}
}

我们会发现 a 数组并不是排序后的,还有重复
打印出集合来看看是不是会自动排好序和去重呢?
在这里插入图片描述
输出后,的确是已经排好序及去重啦~

可能有人会问,那么结构体该如何使用集合排序呢?
这里介绍一种我个人比较喜欢的方法:运算符重载
运算符重载十分方便,尤其是在二分,C++STL及sort等对结构体进行操作时
先来说下运算符重载

struct Node//定义一个结构体
{
	int first_data;
	int second_data;
}input_data[100];

bool operator < (const Node &a , const Node &b)//运算符重载
{
    return (a.first_data == b.first_data ? a.first_data > b.first_data : a.second_data > b.second_data);
}

这样,我们就实现了自己的比较规则,实现重载
运算符重载时,注意这么几个问题:
1.注意,运算符必须与其类型相同,例如 > = < 为bool , + - * 为 int 或long long等
2.括号里的数据,必须要有 const 修饰
3.注意,数据前必须加上地址 & , 表示操作会改变实际结构体的值

只要加上这样的一段运算符重载,就能实现啦~

3.初试身手

我们一起来看下这道题,完善对于集合的理解

时间限制: 1 Sec 内存限制: 128 MB 文件名 set.*
题目描述:
有 N 个正整数,请输出其去重及按升序输出的结果
输入:
第一行,为一个正整数 N , 表示输入数据的个数
以下 N 行,每行一个正整数 Ni,表示一个未排序数据
输出:
多行数据,输出其去重及按升序输出的结果,每行一个正整数
样例输入:

5
4
1
3
3
6

样例输出:

1
3
4
6

说明:

数据范围:
N < 10^4
Ni < 10^9
提示:
分析此题,不难发现这和集合的两大特点全都吻合,可以考虑使用集合

标程:

#include <algorithm>
#include <cstdio>
#include <iostream>
#include <set>
using namespace std;

int main()
{
	set <int> set_data;
	int n;
	scanf("%d" , &n);
	int data;
	while(n--)
	{
		scanf("%d" , &data);
		set_data.insert(data);
	}
	set <int> :: iterator it;
	for(it = set_data.begin() ; it != set_data.end() ; it++)
	{
		printf("%d\n" , *it);
	}

	return 0;
}

运行结果:
在这里插入图片描述
可以看到,答案为正确的
这就是集合的基本操作啦~

总结

今天我们了解了集合这个数据结构,也一起研究了集合的特点及代码实现
以后可以在编程中利用好它的特点优化代码
下章预告:数据结构系列(二) 集合的升级——并查集

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值