unordered_map、unordered_set使用

unordered_map

头文件

#include <iostream>
#include <unordered_map>
using namespace std;

增删查改

unordered_map底层实现为哈希表,增删效率与查找效率都是O(1)

增加元素

  1. emplace(key,value)
  2. insert(pair<T,T> p)
  3. 数组修改法
//unordered_map 三种增加元素的方式
//	insert(pair)
//	emplace(key,value)
//	m[key] = value
#include <iostream>
#include <unordered_map>
using namespace std;

void showMap(unordered_map<int,int> &m){
	unordered_map<int,int>::iterator it;
	for(it=m.begin();it!=m.end();it++){
		cout<<"key: "<<it->first<<", "<<"value: "<<it->second<<endl;
	}
}

int main(int argc, char *argv[]){
	unordered_map<int,int> m;
	m.insert(make_pair(1,2));
	m.insert(pair<int,int>(3,4));
	m[2]=3;
	m.emplace(4,5);

	//测试已有键插入
	//已有键:1,2,3,4
	m.insert(make_pair(1,3));
	m.emplace(4,2);
	m[2] = 4;

	showMap(m);
}
  • 共同点:插入的都是键值对,区别只是键值对的形式不同。
  • 不同:使用emplace与insert插入键值对时,如果unordered_map之前已经有这个键,则无法插入,最终这个键对应的值也没有被修改;使用下标插入时,如果之前已经有这个键了,则把该键对应的值修改为新值。

删除元素

使用erase函数删除
参数:

  1. 迭代器
  2. 两个迭代器,删除这两个迭代器范围内的键值对。注: 传入参数为(迭代器1,迭代器2),删除元素的范围是[迭代器1指向元素, ([迭代器2]-1)指向元素]。
	unordered_map<string,int> m;
	m.emplace("张三",0);
	m.emplace("李四",1);
	m.emplace("王五",2);

	//通过键删除
	//m.erase("张三");

	//通过迭代器删除
	//unordered_map<string,int>::iterator it = m.begin();
	//m.erase(it);

	//通过迭代器范围删除
	unordered_map<string,int>::iterator it1 = m.begin();
	it1++;
	m.erase(it1,m.end());
	showMap(m);

查找元素

  1. count(): 参数为键,如果找到返回1,反之返回0。
  2. find():参数为键,如果找到返回对应位置迭代器,反之返回容器末尾迭代器。
	unordered_map<string,int>m;
	m.insert(make_pair("张三",0));
	m.insert(make_pair("李四",1));
	m.insert(make_pair("王五",2));

	if(m.count("张三")) cout<<"张三"<<endl;
	unordered_map<string,int>::iterator it = m.find("李四");
	if(it!=m.end()) cout<<"李四: "<<it->second<<endl;

unordered_set

增加元素

和unordered_map类似,主要是通过insert函数和emplace函数实现增加元素

//头文件
#include <iostream>
#include <unordered_set>
using namespace std;

void showSet(unordered_set<string> &s){
	unordered_set<string>::iterator it;
	for(it=s.begin();it!=s.end();it++){
		cout<<*it<<" ";
	}
	cout<<endl;
}

int main(){
	//增加元素 insert emplace
	unordered_set<string> s;
	s.insert("张三");
	s.emplace("李四");
	showSet(s);
}

删除元素

删除元素也与unordered_map类似,使用erase函数,并且有三种参数传递模式

  1. 传值
  2. 传对应位置的迭代器
  3. 传入两个迭代器,删除范围内的元素。注: 传入参数为(迭代器1,迭代器2),删除元素的范围是[迭代器1指向元素, ([迭代器2]-1)指向元素]。
	//删除元素
	//按值删除
	//s.erase("张三");

	//按迭代器删除
	//unordered_set<string>::iterator it = s.begin();
	//s.erase(it);

	//按迭代器范围删除
	unordered_set<string>::iterator it = s.begin();
	it++;
	s.erase(it,s.end());
	showSet(s);

自定义类型的哈希表

因为unordered_set和unordered_map的底层实现都是哈希表,而默认哈希函数是针对基本数据类型的,对于用户自定义的类型(类、结构体),需要重写哈希函数。
需要做的有两步:

  1. 在类中重载==运算符,使得编译器知道在发生哈希碰撞时如何处理
  2. 重写hash函数,具体做法为,自定义一个hash结构体,并重载()运算符,返回size_t类型的变量,一般哈希的方式为异或。
    最后,在定义unordered_map时,把结构体作为第三个参数传入<>中。
//实现时间类的运算符重载
#include <iostream>
#include <unordered_map>
using namespace std;
class Line{
	private:
		int len,col;
	public:
		Line(){}
		Line(int _l, int _c):len(_l),col(_c){}
		~Line(){
			cout << "这是析构函数" << endl;
		}
		void print() const {
			cout << len << " " << col << endl;
		}
		bool operator==(const Line &l) const{
			return len == l.len && col == l.col;
		}
		int getLen() const{
			return len;
		}
		int getCol() const{
			return col;
		}
};
struct createhash{
	size_t operator()(const Line &l) const{
		return hash<int>()(l.getLen()) ^ hash<int>()(l.getCol());
	}
};
int main(){
	unordered_map<Line,int,createhash> m;
	Line *l = new Line(2,3);
	l->print();
	//delete l;
	return 0;
}
posted @ 2023-06-02 15:59  智子lock  阅读(22)  评论(0编辑  收藏  举报