当前位置: 首页 > backend >正文

C++ unordered_set基础概念、对象创建、赋值操作、数据插入、数据删除、代码练习 1 2

unordered_set的底层是哈希表。

增删改查的时间复杂度:

数组 O(n)  二叉树O(logn)  哈希表 O(1)

哈希表的本质原理:哈希键--(哈希函数)--哈希值--(取模、位于)--桶/ID

这里的哈希键一般是任意类型,所以需要先通过哈希函数转换为整数,我们叫他哈希值,再通过取模(一般使用的时候采用位于运算),映射到某个桶中。这样就可以把任意类型的数据存储到数组中,且能够快速查找到。

桶:下标索引又叫桶ID,桶ID是用来索引到某个具体位置的桶。因为用的取模,所以得到的桶ID都是连续的自然数,这样桶可以用数组来实现

哈希冲突:是指两个元素的键不同,但是它们计算得到桶ID一样的情况

哈希冲突解决方案:常见的解决方案,是在一个桶中放多个元素,这样就可以通过哈希算法快速找到桶,再通过遍历桶中所有元素,来实现快速查找。在STL中,数据不是存在一个bucket桶中,而是利用了(bucket<<1)和(bucket<<1 )+ 1 两个位置,并且把所有桶中元素串联成一个链表,它里面的元素,是从(bucket<<1)的位置作为链表的起点,(bucket<<1 )+ 1的位置作为链表终点,来存储哈希表中所有桶ID为bucket的节点。所有的哈希表节点会被链接到一个全局的双向链表中,双向链表有个虚拟头结点_Head

哈希表的增删查:哈希表的元素插入,便是直接插入到头部。哈希表的元素查找:从后往前来查找。哈希表的元素删除:先找到桶ID,然后从后往前逆序遍历,执行双向链表的删除操作。

散列容器:unordered_set unordered_map

线形容器:vector、string、list

树形容器:set、multiset、map、multimap

线性模拟树:priority_queue

unordered_set 对象创建,代码见下

#include<iostream>
#include<unordered_set>using namespace std;void printUSet(const unordered_set<int>& s) {for (unordered_set<int>::const_iterator it = s.begin(); it != s.end(); it++) {cout << *it << " ";}cout << endl;}
int main() {// 1 默认构造函数unordered_set<int> s1;cout << "s1: ";printUSet(s1);// 2 初始化列表unordered_set<int> s2_1 = { 9, 8, 7, 6, 5, 1, 2, 3, 4, 6 };cout << "s2_1: ";printUSet(s2_1);unordered_set<int> s2_2 ({ 9, 8, 7, 6, 5, 1, 2, 3, 4, 6, 6, 6, 6, 6 });cout << "s2_2: ";printUSet(s2_2);// 3 迭代器unordered_set<int> s3(s2_1.begin(), s2_1.end());cout << "s3: ";printUSet(s3);// 4 拷贝构造unordered_set<int> s4(s2_2);cout << "s3: ";printUSet(s3);return 0;
}

unordered_set 赋值操作,代码见下

#include<iostream>
#include<unordered_set>using namespace std;void printUSet(const unordered_set<int>& s) {for (unordered_set<int>::const_iterator it = s.begin(); it != s.end(); it++) {cout << *it << " ";}cout << endl;}
int main() {unordered_set<int> s = {9, 8, 5, 2, 1, 1};cout << "s: ";printUSet(s);// = set对象unordered_set<int> s1;s1 = s;cout << "s1: ";printUSet(s1);// = 初始化列表unordered_set<int> s2;s2 = { 9,3, 4, 6, 1, 3 };cout << "s2: ";printUSet(s2);return 0;
}

unordered_set 大小操作,代码见下

#include<iostream>
#include<unordered_set>using namespace std;void printUSet(const unordered_set<int>& s) {for (unordered_set<int>::const_iterator it = s.begin(); it != s.end(); it++) {cout << *it << " ";}cout << endl;}
int main() {unordered_set<int> s1;cout << "s1.empty()" << s1.empty() << endl;cout << "s1.size()" << s1.size() << endl;unordered_set<int> s2 = {5, 6, 8, 3, 1, 3};cout << "s2.empty()" << s2.empty() << endl;cout << "s2.size()" << s2.size() << endl;unordered_multiset<int> s3 = { 5, 6, 8, 3, 1, 3, 1, 1, 1 };cout << "s3.empty()" << s3.empty() << endl;cout << "s3.size()" << s3.size() << endl;return 0;
}

结果见下,助于理解

unordered_set 数据插入,代码见下

#include<iostream>
#include<unordered_set>using namespace std;void printUSet(const unordered_set<int>& s) {for (unordered_set<int>::const_iterator it = s.begin(); it != s.end(); it++) {cout << *it << " ";}cout << endl;}
int main() {unordered_set<int> s1;s1.insert(5); printUSet(s1);s1.insert(4); printUSet(s1);s1.insert(7); printUSet(s1);s1.insert(1); printUSet(s1);s1.insert(2); printUSet(s1);s1.insert(6); printUSet(s1);s1.insert(9); printUSet(s1);vector<int> v = { 1, 9, 9, 0 };s1.insert(v.begin(), v.end());printUSet(s1);return 0;
}

结果见下,助于理解:

5
5 4
5 4 7
5 4 7 1
5 4 7 1 2
5 4 7 1 2 6
5 4 7 9 1 2 6
5 4 7 9 1 2 6 0

最后一行这个结果只是将不重复的0插入了set中,具体原因可见源码截图

unordered_set 数据查找,代码见下

#include<iostream>
#include<unordered_set>using namespace std;void printUSet(const unordered_set<int>& s) {for (unordered_set<int>::const_iterator it = s.begin(); it != s.end(); it++) {cout << *it << " ";}cout << endl;}
int main() {unordered_set<int> s = { 4, 3, 7, 9, 1 };unordered_set<int>::iterator it = s.find(3);if (it != s.end()) {cout << "find: " << *it << endl;}it = s.find(10);if (it == s.end()) {cout << "can't find 10" << endl;}return 0;
}

unordered_set 数据删除,代码见下

#include<iostream>
#include<unordered_set>using namespace std;void printUSet(const unordered_set<int>& s) {for (unordered_set<int>::const_iterator it = s.begin(); it != s.end(); it++) {cout << *it << " ";}cout << endl;}
int main() {unordered_set<int> s = { 8, 4, 3, 7, 1 };s.erase(3);printUSet(s);unordered_set<int>::iterator it = s.find(4);if (it != s.end()) {s.erase(it);}printUSet(s);s = { 13, 14, 56, 72, 34, 45, 23, 67 };unordered_set<int>::iterator it1 = s.find(23);unordered_set<int>::iterator it2 = s.find(14);//s.erase(it1, it2); //不建议用printUSet(s);s.clear();return 0;
}

unordered_set 数据统计,代码见下

#include<iostream>
#include<unordered_set>using namespace std;void printUSet(const unordered_set<int>& s) {for (unordered_set<int>::const_iterator it = s.begin(); it != s.end(); it++) {cout << *it << " ";}cout << endl;}
int main() {unordered_set<int> s = { 5, 6, 7, 8, 9 };for (int i = 0; i < 8; i += 2) {cout << "元素:" << i << "的出现次数为" << s.count(i) << endl;}printUSet(s);return 0;
}

代码练习 1,对应力扣,相交链表

/*** Definition for singly-linked list.* struct ListNode {*     int val;*     ListNode *next;*     ListNode(int x) : val(x), next(NULL) {}* };*/
class Solution {
public:ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {unordered_set<ListNode*> us;while(headA){us.insert(headA);headA = headA -> next;} while(headB){if(us.find(headB) != us.end()){return headB;}headB = headB->next;}return NULL;}};

代码练习 2,对应力扣,重复DNA序列

class Solution {
public:vector<string> findRepeatedDnaSequences(string s) {unordered_multiset<string> ums;vector<string> ans;for(int i=0; i+10 <= s.size(); ++i){string sub = s.substr(i, 10);ums.insert(sub);if(ums.count(sub) == 2){ans.push_back(sub);}}return ans;}
};

http://www.xdnf.cn/news/14624.html

相关文章:

  • 前端开发面试题总结-vue3框架篇(二)
  • 《map和set的使用介绍》
  • stm32串口(uart)2转发到串口(uart)3实现
  • Qt实战:自定义二级选项框 | 附完整源码
  • 为车辆提供路径规划解决方案:技术演进、挑战与未来蓝图
  • 网络编程及原理(六):三次握手、四次挥手
  • 【软考高级系统架构论文】论NoSQL数据库技术及其应用
  • 通过事件过滤器拦截QRadioButton点击事件
  • 算法第38天|322.零钱兑换\139. 单词拆分
  • 数据分析和可视化:Py爬虫-XPath解析章节要点总结
  • 【Python进阶系列】第9篇:聊聊 Python 中常用的第三方库
  • C++递归应用
  • 7.3.1二叉排序树
  • 【编译原理】语句的翻译
  • FPGA基础 -- Verilog 共享任务(task)和函数(function)
  • VUE3 Element UI el-button type icon
  • King’s LIMS 系统引领汽车检测实验室数字化转型
  • QT历史版本,5.15.2使用清华源半小时安装速成
  • GitHub Actions + SSH 自动部署教程
  • 日常运维问题汇总-24
  • 分清display三个属性
  • MySQL之事务深度解析
  • 为什么你的vue项目连接不到后端
  • 基于微信小程序的美食点餐订餐系统
  • JSON 数据格式详解
  • SEO已死,GEO当立:AI搜索时代的新游戏规则
  • Hollywood: The World’s Most Effective Propaganda System
  • VR 看房:突破成长痛点,展望未来趋势
  • 基于深度学习的智能视频行为识别系统:技术与实践
  • 如何使用 Dockerfile 创建自定义镜像