数据结构与算法之哈希表

数据结构与算法之哈希表



哈希表

哈希表是一种将value值与key值构建映射关系,以达到快速查询的数据结构。
在c++STL中实现了三种哈希结构:数组、set、map。
其中数组就没什么好介绍的了。本文主要介绍set、map这两种哈希结构。此外,也实现了一个简单的哈希表。


一、set集合介绍

1、std::set集合

(1)底层实现:红黑树
(2)是否排序:根据key值进行排序
(3)key值能否重复:key值不能重复
(4)key值能否修改:key值不能修改
(5)查询效率:O(logn)
(6)增删效率:O(logn)

2、std::multiset集合

(1)底层实现:红黑树
(2)是否排序:根据key值进行排序
(3)key值能否重复:key值可重复
(4)key值能否修改:key值不能修改
(5)查询效率:O(logn)
(6)增删效率:O(logn)

3、std::unordered_set集合

(1)底层实现:哈希表
(2)是否排序:无序
(3)key值能否重复:key值不可重复
(4)key值能否修改:key值不能修改
(5)查询效率:O(1)
(6)增删效率:O(1)

二、map集合介绍

1、std::map

(1)底层实现:红黑树
(2)是否排序:根据key值进行排序
(3)key值能否重复:key值不能重复
(4)key值能否修改:key值不能修改
(5)查询效率:O(logn)
(6)增删效率:O(logn)

2、std::multimap集合

(1)底层实现:红黑树
(2)是否排序:根据key值进行排序
(3)key值能否重复:key值可重复
(4)key值能否修改:key值不能修改
(5)查询效率:O(logn)
(6)增删效率:O(logn)

3、std::unordered_map集合

(1)底层实现:哈希表
(2)是否排序:无序
(3)key值能否重复:key值不可重复
(4)key值能否修改:key值不能修改
(5)查询效率:O(1)
(6)增删效率:O(1)

哈希表的简单实现

MyHashSet类

struct ListNode {
    int val;
    ListNode *next;
    ListNode(int x) : val(x), next(NULL) {}
};
class MyHashSet{
public:
	MyHashSet(const int& range);
	~MyHashSet();
	void add(int key); //添加键值
	void remove(int key); //删除键值
	bool contains(int key);//查找键值
private:
	int KeyRange;
	vector<ListNode*> HashTable;
};

构造函数

为了尽量避免哈希冲突建议将rang设置为素数且尽量设置的比较大

MyHashSet::MyHashSet(const int& range){
	KeyRange = range;
	for(int i = 0; i < range; ++i){
		HashTable.push_back(nullptr);
	}
}

析构函数

MyHashSet::~MyHashSet(){
	for(int i = 0; i < KeyRange; ++i){
		if(HashTable[i] == nullptr)
			continue;
		ListNode* cur = HashTable[i];
		HashTable[i] = nullptr;
		while(cur != nullptr){
			ListNode* temp = cur->next;
			delete cur;
			cur = temp;
		}
	}
}

添加键值

void MyHashSet::add(int key){
	if(this->contains(key))//判断该key是否已经存在
		return;
	int n = key % KeyRange;
	ListNode* newNode = new ListNode(key);
	newNode->next = HashTable[n];
	HashTable[n] = newNode;
}

移除键值

void MyHashSet::remove(int key){
	int n = key % KeyRange;
	ListNode* dummy = new ListNode(0); //虚头结点
	dummy->next = HashTable[n];
	ListNode* cur = dummy->next;
	ListNode* pre = dummy;
	while(cur != nullptr){
		if(cur->val = key){
			pre->next = cur->next;
			delete cur;
			break;
		}
		pre = cur;
		cur = cur->next;
	}
	HashTable[n] = dummy->next;
	delete dummy;
}

查找键值

bool MyHashSet::contains(int key){
	int n = key % KeyRange;
	ListNode* cur = HashTable[n];
	while(cur != nullptr){
		if(cur->val == key)
			return true;
		cur = cur->next;
	}
	return false;
}

以上代码如有问题,请及时留言。


总结

MyHashSet类只是对哈希表的简单实现,当数据量很大时不会自动扩展数组,及重新排列key值。需要用到相关哈希函数时,建议使用STL标准库中的set、map。当然如果数据量不大,也可以用数组实现哈希,例如统计字符串中小写字符的数量。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值