C++ set替换vector进行优化

demo

#include <iostream>
#include <set>

int main() {
	// 创建一个存储整数的std::set
	std::set<int> mySet;

	// 插入元素
	mySet.insert(300);
	mySet.insert(1);
	mySet.insert(2);
	mySet.insert(3);  
	mySet.insert(3);  // 重复元素不会被插入
	mySet.insert(300);  // 重复元素不会被插入
	mySet.insert(300);  // 重复元素不会被插入

	// 输出集合中的元素
	std::cout << "Set elements: ";
	for (auto it = mySet.begin(); it != mySet.end(); ++it)
	{
		std::cout << *it << " ";
	}
	std::cout << std::endl;

	// 查找元素
	auto findIt = mySet.find(2);
	if (findIt != mySet.end())
	{
		std::cout << "Element 2 found in the set." << std::endl;
	} 
	else
	{
		std::cout << "Element 2 not found in the set." << std::endl;
	}

	// 删除元素
	mySet.erase(1);
	std::cout << "Set elements after erasing 1: ";
	for (auto it = mySet.begin(); it != mySet.end(); ++it)
	{
		std::cout << *it << " ";
	}
	std::cout << std::endl;

	// 检查集合是否为空
	if (mySet.empty()) 
	{
		std::cout << "The set is empty." << std::endl;
	}
	else
	{
		std::cout << "The set is not empty." << std::endl;
	}

	// 获取集合的大小
	std::cout << "The size of the set is: " << mySet.size() << std::endl;

	// 清除集合中所有内容
	mySet.clear();
	std::cout << "Set elements after clearing: ";
	for (auto it = mySet.begin(); it != mySet.end(); ++it)
	{
		std::cout << *it << " ";
	}
	std::cout << std::endl;

	// 再次检查集合是否为空
	if (mySet.empty())
	{
		std::cout << "The set is empty after clearing." << std::endl;
	} 
	else 
	{
		std::cout << "The set is not empty after clearing." << std::endl;
	}

	return 0;
}    

在这里插入图片描述

代码解释:

  1. 创建集合:使用std::set<int> mySet;创建一个存储整数的std::set
  2. 插入元素:通过insert方法向集合中插入元素,重复元素不会被插入。
  3. 遍历集合:使用迭代器遍历集合中的元素并输出。
  4. 查找元素:使用find方法查找指定元素,如果找到则返回指向该元素的迭代器,否则返回end()
  5. 删除元素:使用erase方法删除指定元素。
  6. 检查集合是否为空:使用empty方法检查集合是否为空。
  7. 获取集合大小:使用size方法获取集合中元素的数量。

底层原理

在C++标准库中,std::set 是一个关联容器,用于存储唯一的元素,并且这些元素会按照一定的顺序排列(默认是升序)。它的底层通常基于红黑树(Red - Black Tree)这种自平衡二叉搜索树(Self - Balancing Binary Search Tree)来实现

1. 二叉搜索树基础

二叉搜索树(Binary Search Tree,BST)是一种二叉树,对于树中的每个节点,其左子树中的所有节点的值都小于该节点的值,而右子树中的所有节点的值都大于该节点的值。这种特性使得在二叉搜索树中进行查找、插入和删除操作的平均时间复杂度为 O ( l o g n ) O(log n) O(logn),其中 n n n 是树中节点的数量。

2. 红黑树的特性

红黑树是一种自平衡的二叉搜索树,它在每个节点上增加了一个存储位来表示节点的颜色(红色或黑色)。通过对任何一条从根到叶子的路径上各个节点着色方式的限制,红黑树确保没有一条路径会比其他路径长出两倍,因而是接近平衡的。红黑树必须满足以下五个性质:

  • 每个节点要么是红色,要么是黑色。
  • 根节点是黑色。
  • 每个叶子节点(NIL节点,空节点)是黑色的。
  • 如果一个节点是红色的,则它的两个子节点都是黑色的。
  • 对每个节点,从该节点到其所有后代叶节点的简单路径上,均包含相同数目的黑色节点。

3. std::set 基于红黑树的实现优势

  • 有序性:由于红黑树是一种二叉搜索树,插入到 std::set 中的元素会根据元素的键值自动排序。例如,插入整数时会按照从小到大的顺序排列。
  • 唯一性:在插入元素时,红黑树会进行比较,如果发现元素已经存在,则不会插入,保证了 std::set 中元素的唯一性。
  • 高效的查找、插入和删除操作:红黑树的自平衡特性保证了树的高度始终保持在 O ( l o g n ) O(log n) O(logn) 级别,因此查找、插入和删除操作的时间复杂度都是 O ( l o g n ) O(log n) O(logn)

4. 插入操作

当向 std::set 中插入一个新元素时,底层的红黑树会执行以下步骤:

  • 按照二叉搜索树的规则找到新元素应该插入的位置。
  • 将新元素插入到该位置,并将其颜色设置为红色。
  • 检查红黑树的性质是否被破坏,如果破坏了则通过一系列的颜色调整和旋转操作来恢复红黑树的性质。

5. 删除操作

当从 std::set 中删除一个元素时,红黑树会执行以下步骤:

  • 按照二叉搜索树的规则找到要删除的节点。
  • 如果该节点有两个子节点,则用其右子树中的最小节点替换该节点,然后删除右子树中的最小节点。
  • 删除节点后,检查红黑树的性质是否被破坏,如果破坏了则通过一系列的颜色调整和旋转操作来恢复红黑树的性质。

6. 查找操作

查找操作相对简单,根据二叉搜索树的特性,从根节点开始比较,如果要查找的元素值小于当前节点的值,则在左子树中继续查找;如果大于当前节点的值,则在右子树中继续查找;如果相等,则找到了该元素。由于红黑树的高度为 O ( l o g n ) O(log n) O(logn),因此查找操作的时间复杂度也是 O ( l o g n ) O(log n) O(logn)

综上所述,std::set 基于红黑树实现,利用红黑树的特性保证了元素的有序性、唯一性以及高效的查找、插入和删除操作。

<think>首先,用户的问题是:“我想在C++中使用set对数组进行排序和去重的方法 请问C++ set头文件实现数组排序和去重的方法”。用户想知道如何在C++中使用set头文件来对数组进行排序和去重。 从系统指令中,我需要: - 所有行内数学表达式用$...$格式。 - 独立公式用$$...$$格式并单独成段。 - LaTeX语法正确。 - 使用中文回答。 - 生成相关问题。 - 回答中引用的段落末尾自然地添加引用标识。 - 回答结构清晰,帮助用户逐步解决问题。 - 保证回答真实可靠。 参考的引用: - 引用[1]: 关于使用set自动排序去重。 - 引用[2]: 关于set在去重和排序中的应用。 - 引用[3]: 关于set的排序和去重特性。 这些引用强调了set的特性:自动排序和去重。用户的问题正是关于这个的。 我的回答应该结构清晰: 1. **解释set的特性**:setC++中是一个关联容器,它存储唯一元素,并根据元素的值自动排序。 2. **给出步骤**:如何用set对数组进行排序和去重。 3. **提供代码示例**:展示具体实现。 4. **解释代码**:简要解释代码的工作原理。 5. **生成相关问题**:在回答结束时添加相关问题。 回答要点: - 使用set可以轻松实现排序和去重,因为set内部使用红黑树实现,保证元素唯一且有序。 - 步骤: - 包含头文件:<set> - 创建一个set,并将数组的元素插入到set中。 - 由于set自动去重和排序,所以可以直接使用。 - 如果需要将结果放回数组,可以从set复制回数组。 - 代码示例:类似引用中的例子。 代码示例参考引用[1]: ```cpp vector<int> v; // 原始数组 set<int> s(v.begin(), v.end()); // 创建set,自动排序和去重 v.assign(s.begin(), s.end()); // 将结果复制回数组 ``` 这应该清晰易懂。 生成相关问题: - 基于用户的问题,生成2-3个相关问题,如: 1. set和multiset的区别是什么? 2. 使用set去重的性能如何? 3. 还有其他方法对数组排序和去重吗? 确保引用标识:在回答中,如果提到引用的内容,自然添加引用标识。例如,在解释set特性时,可以引用[2]或[3]。 最终回答结构: 1. 开头介绍set的特性。 2. 给出具体方法和代码。 3. 解释代码。 4. 结束生成相关问题。</think>### C++ 中使用 set 实现数组排序和去重的方法 在 C++ 中,`set` 是一个关联容器,它基于红黑树实现,能自动对元素进行**排序(升序)**和**去重**。其核心特性是: - **排序**:元素插入时自动按升序排列(可通过自定义比较器改变)。 - **去重**:每个元素唯一,重复值会被自动移除。 - **高效性**:插入和查找的平均时间复杂度为 $O(\log n)$,适合处理需要排序和去重的场景[^1][^2][^3]。 以下是使用 `set` 对数组进行排序和去重的完整步骤和代码示例: #### 步骤说明 1. **包含头文件**:引入 `<set>` 和 `<vector>`(如果使用数组)。 2. **创建 set 对象**:将数组元素插入 setset 会自动去重并排序。 3. **换回数组(可选)**:如果需要结果以数组形式输出,将 set 的元素复制回原数组或新容器。 #### 代码示例 ```cpp #include <iostream> #include <vector> #include <set> // 包含 set 头文件 int main() { // 原始数组(可替换为任意整数数组) std::vector<int> arr = {5, 2, 8, 2, 5, 1, 8, 9}; // 使用 set 实现排序和去重 std::set<int> s(arr.begin(), arr.end()); // 将数组元素插入 set,自动去重和排序 // 将结果复制回数组(可选) arr.assign(s.begin(), s.end()); // 输出结果 std::cout << "排序和去重后的数组: "; for (int num : arr) { std::cout << num << " "; } // 输出: 1 2 5 8 9 return 0; } ``` #### 代码解释 - **`std::set<int> s(arr.begin(), arr.end())`**:通过迭代器范围构造 set,元素自动去重并按升序排序(时间复杂度 $O(n \log n)$)。 - **`arr.assign(s.begin(), s.end())`**:将 set 的元素复制回原数组(时间复杂度 $O(n)$)。 - **特性**: - set 默认升序排序,如需降序,可声明为 `std::set<int, std::greater<int>>`。 - 如果保留重复元素,需使用 `multiset`(但会失去去重功能)[^3]。 #### 优点与注意事项 - **优点**:代码简洁,无需手动实现排序算法(如快速排序)或哈希表。 - **适用场景**:元素类型需支持比较(如整数、字符串),否则需自定义比较器。 - **性能**:适合中小规模数据;大规模数据时,`unordered_set`(基于哈希)可能更快,但需手动排序[^2]。 通过 set 实现排序和去重,能显著提升代码效率,尤其在需要唯一有序数据的场景中[^1][^2]。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值