20.哈希

一.unordered系列关联式容器

unordered_set 和 unordered_map 中序遍历都是无序的

二.unordered_set的介绍

cplusplius文档链接如下:

https://legacy.cplusplus.com/reference/unordered_set/unordered_set/

平时使用不用管

1.接口介绍

只能说,set和unordered_set的使用都是差不多的(90%),但是由于底层的差别(set(红黑树),unordered_set(哈希表)),有一些差别,如下:

从unordered_set没提供的rbegin()和rend()可以知道

2.代码测试

1.接口测试

cpp 复制代码
#include<unordered_set>
#include<unordered_map>
#include<set>
#include<iostream>
#include <time.h>
#include <vector>
using namespace std;

void test_set1()
{
	unordered_set<int> s = { 3,1,6,7,8,2 };
	unordered_set<int>::iterator it = s.begin();
	while (it != s.end())
	{
		cout << *it << " ";
		++it;
	}
	cout << endl;

	for (auto e : s)
	{
		cout << e << " ";
	}
	cout << endl;
}

这里验证了,我们的unordered_set插入数据是无序的

2.性能测试

cpp 复制代码
int test_set2()
{
	const size_t N = 10000000;

	unordered_set<int> us;
	set<int> s;

	vector<int> v;
	v.reserve(N);
	srand(time(0));
	for (size_t i = 0; i < N; ++i)
	{
		//v.push_back(rand()); // N比较大时,重复值比较多
		//v.push_back(rand()+i); // 重复值相对少
		v.push_back(i); // 没有重复,有序
	}

	size_t begin1 = clock();
	for (auto e : v)
	{
		s.insert(e);
	}
	size_t end1 = clock();
	cout << "set insert:" << end1 - begin1 << endl;

	size_t begin2 = clock();
	for (auto e : v)
	{
		us.insert(e);
	}
	size_t end2 = clock();
	cout << "unordered_set insert:" << end2 - begin2 << endl;

	int m1 = 0;
	size_t begin3 = clock();
	for (auto e : v)
	{
		auto ret = s.find(e);
		if (ret != s.end())
		{
			++m1;
		}
	}
	size_t end3 = clock();
	cout << "set find:" << end3 - begin3 << "->" << m1 << endl;

	int m2 = 0;
	size_t begin4 = clock();
	for (auto e : v)
	{
		auto ret = us.find(e);
		if (ret != us.end())
		{
			++m2;
		}
	}
	size_t end4 = clock();
	cout << "unorered_set find:" << end4 - begin4 << "->" << m2 << endl;

	cout << "插入数据个数:" << s.size() << endl;
	cout << "插入数据个数:" << us.size() << endl << endl;

	size_t begin5 = clock();
	for (auto e : v)
	{
		s.erase(e);
	}
	size_t end5 = clock();
	cout << "set erase:" << end5 - begin5 << endl;

	size_t begin6 = clock();
	for (auto e : v)
	{
		us.erase(e);
	}
	size_t end6 = clock();
	cout << "unordered_set erase:" << end6 - begin6 << endl << endl;

	return 0;
}

unordered_set有序性能低,set有序性能高

三.unordered_map的介绍

1.接口介绍

2.代码测试

cpp 复制代码
void test_map1()
{
	unordered_map<string, string> dict;
	dict.insert({ "left", "左边" });
	dict["sort"];
	dict["sort"] = "排序";
}

和map的基础功能是一样的

四.题目

1.

https://leetcode.cn/problems/n-repeated-element-in-size-2n-array/description/

cpp 复制代码
class Solution {
public:
    int repeatedNTimes(vector<int>& A) {
        size_t N = A.size() / 2;
        // 用unordered_map统计每个元素出现的次数
        unordered_map<int, int> m;
        for(auto e : A)
            m[e]++;

        // 找出出现次数为N的元素
        for(auto& e : m)
        {
            if(e.second == N)
                return e.first;
        }
    }
};

2.

https://leetcode.cn/problems/intersection-of-two-arrays/description/

cpp 复制代码
class Solution {
public:
    vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {
        // 用unordered_set对nums1中的元素去重
        unordered_set<int> s1;
        for (auto e : nums1)
            s1.insert(e);

        // 用unordered_set对nums2中的元素去重
        unordered_set<int> s2;
        for (auto e : nums2)
            s2.insert(e);

        // 遍历s1,如果s1中某个元素在s2中出现过,即为交集
        vector<int> vRet;
        for (auto e : s1)
        {
            if (s2.find(e) != s2.end())
                vRet.push_back(e);
        }

        return vRet;
    }
};

3.

https://leetcode.cn/problems/first-unique-character-in-a-string/description/

cpp 复制代码
class Solution {
public:
    int firstUniqChar(string s) {
        int count[26]={0};
        for(auto ch:s)
        {
            count[ch-'a']++;
        }
        for(int i=0;i<s.size();i++)
        { 
            if(count[s[i]-'a']==1)
            {
                return i;
            }
        }
        
            return -1;
        
    }
};

五.哈希的概念的讲解

1.闭散列

找位置又有两种方式:

a.线性探测

有没有可能找不到位置(位置被占满了),不会,后面我们会提出负载因子的概念

b.二次探测

c.其他规则

这里不展开讨论

2.开散列

六.哈希的大概实现

cpp 复制代码
#pragma once
#include <vector>



enum State
{
    EXIST,
    EMPTY,
    DELETE
};

template<class K, class V>
struct HashData
{
    pair<K, V> _kv;
    State _state = EMPTY;
};

template<class K, class V>
class HashTable
{
private:
    vector<HashData<K, V>> _tables;
};
相关推荐
Zsy_0510032 小时前
【数据结构】二叉树OJ
数据结构
快乐zbc2 小时前
【C++ 基础】:给定一个指针 p,你能判断它是否指向合法的对象吗?
c++
岁忧2 小时前
GoLang五种字符串拼接方式详解
开发语言·爬虫·golang
tyatyatya2 小时前
MATLAB基础数据类型教程:数值型/字符型/逻辑型/结构体/元胞数组全解析
开发语言·matlab
sulikey3 小时前
C++类和对象(下):初始化列表、static、友元、内部类等核心特性详解
c++·static·初始化列表·友元·匿名对象·内部类·编译器优化
心无旁骛~3 小时前
python多进程和多线程问题
开发语言·python
星云数灵3 小时前
使用Anaconda管理Python环境:安装与验证Pandas、NumPy、Matplotlib
开发语言·python·数据分析·pandas·教程·环境配置·anaconda
kaikaile19953 小时前
基于遗传算法的车辆路径问题(VRP)解决方案MATLAB实现
开发语言·人工智能·matlab
四问四不知4 小时前
Rust语言进阶(结构体)
开发语言·后端·rust
q***9944 小时前
index.php 和 php
开发语言·php