C++哈希表实现

#include<stdio.h>
#include<stdlib.h>
#include<time.h>

#define HASHLENGTH 10

struct node
{
	int data;
	struct node *next;
};
struct node hash[HASHLENGTH];
typedef struct node * HashNode;

int Hash(int k)
{
	return k%HASHLENGTH;
}

void CreateHash()
{
	for(int i=0; i<HASHLENGTH; i++)
	{
		hash[i].data = i;
		hash[i].next = NULL;
	}
}
void PrintOneLink(struct node h)
{
	HashNode ptr = h.next;
	while(ptr != NULL)
	{
		printf("%d ", ptr->data);
		ptr = ptr->next;
	}
	printf("\n");
}

void PrintHash()
{
	for(int i=0; i<HASHLENGTH; i++)
	{
		printf("hash[%d]:", i);
		PrintOneLink(hash[i]);
	}
}

bool SearchHash(int data)
{
	int p = Hash(data);
	HashNode ptr = hash[p].next;
	while(ptr != NULL && ptr->data!=data)
	{
		ptr = ptr->next;
	}
	if(ptr == NULL) 
		return false;
	return true;
}

int InsertHash(int data)
{
	if(SearchHash(data)==true)
	{
		return 0;
	}
	else
	{
		int p = Hash(data);
		HashNode hn = (HashNode)malloc(sizeof(struct node));
		hn->data = data;
		hn->next = NULL;
		if(hash[p].next == NULL)
		{
			hash[p].next = hn;
		}
		else
		{
			hn->next = hash[p].next;
			hash[p].next = hn;
		}
	}
	return 1;
}

void DeleteHash(int data)
{
	if(SearchHash(data)==true)
	{
		int p = Hash(data);
		HashNode ptr = hash[p].next;
		HashNode prePtr = ptr;
		if(ptr->data == data)
		{
			hash[p].next = ptr->next;
			free (ptr);
		}
		else
		{
			while(ptr != NULL && ptr->data != data)
			{
				prePtr = ptr;
				ptr = ptr->next;
			}
			prePtr->next = ptr->next;
			free(ptr);
		}
	}
	else
	{
		printf("Don't have the number\n");
	}
}

void HashTest()
{
	CreateHash();
	int data = -99;
	srand( (unsigned)time(NULL) );
	for(int i=0; i<30; i++)
	{
		data = rand();
		InsertHash(data);
	}
	PrintHash();
	printf("Enter a number to delete:");
	while(scanf("%d", &data) != EOF)
	{
		DeleteHash(data);
		PrintHash();
		printf("Enter a number to delete:");
	}
}

int main()
{
	HashTest();
	return 0;
}


<think>我们正在寻找C++哈希表实现示例代码。根据引用[4]和[5],我们可以构建一个简单的哈希表,它应该包括以下部分: 1.哈希函数:用于将键映射到索引。 2.冲突解决:这里我们使用开放寻址法(线性探测)来处理冲突。3.动态扩容:当装载因子超过阈值(如0.7)时,进行扩容并重新哈希。 引用[4]提供了一个哈希表的基本框架,包括状态枚举(空、存在、删除)和哈希表结构(使用vector存储,每个元素包含键值对和状态)。同时,引用[3]给出了自定义类型哈希函数的示例,但我们现在主要关注基本类型的哈希表。我们将实现一个支持插入、查找和删除操作的哈希表,并处理扩容。步骤:1.定义哈希表元素的状态(EMPTY,EXIST, DELETE)。 2.定义哈希表元素结构体,包含键值对和状态。3.哈希表类包含一个存储元素的vector和有效数据个数。4.实现哈希函数:这里我们使用除留余数法,并且为了通用性,我们使用一个可调用的哈希函数对象(默认处理整型,对于字符串等需要特化)。5.插入操作:计算索引,如果冲突则线性探测,直到找到空位置或已删除的位置。如果装载因子超过阈值,则扩容并重新插入所有元素。 6.查找操作:计算索引,然后从该位置开始线性探测,直到找到键相同的存在状态元素,或者遇到空位置。7.删除操作:找到对应的元素,将其状态标记为删除,并减少有效数据个数。注意:在重新哈希时,需要将原表中的所有存在状态的元素重新插入到新表中。 下面我们给出一个C++实现的示例代码:</think>### C++ 哈希表实现示例代码 以下是基于开放寻址法的C++哈希表完整实现,包含插入、查找、删除和动态扩容功能: ```cpp #include <iostream> #include <vector> #include <functional> // std::hash // 哈希表元素状态标记 enum State { EMPTY, // 空槽位 EXIST, // 有数据 DELETE // 已删除 }; // 哈希表元素结构 template <typename K, typename V> struct HashNode { std::pair<K, V> kv; // 键值对 State state = EMPTY; // 初始状态为空 }; // 哈希表主体 template <typename K, typename V, typename Hash = std::hash<K>> class HashTable { private: std::vector<HashNode<K, V>> _table; // 存储桶数组 size_t _size = 0; // 有效元素数量 const double MAX_LOAD_FACTOR = 0.7; // 扩容阈值 // 获取键的哈希值[^3][^5] size_t _hash(const K& key) const { return Hash()(key) % _table.size(); } // 扩容操作 void _resize() { if (static_cast<double>(_size) / _table.size() < MAX_LOAD_FACTOR) return; // 创建新表(2倍容量) std::vector<HashNode<K, V>> newTable(_table.size() * 2); std::swap(_table, newTable); _size = 0; // 迁移数据[^4] for (auto& node : newTable) { if (node.state == EXIST) { insert(node.kv.first, node.kv.second); } } } public: HashTable(size_t initialSize = 10) : _table(initialSize) {} // 插入元素 bool insert(const K& key, const V& value) { _resize(); // 检查是否需要扩容 size_t index = _hash(key); size_t start = index; // 线性探测解决冲突[^3] do { if (_table[index].state != EXIST) { _table[index].kv = {key, value}; _table[index].state = EXIST; _size++; return true; } // 键已存在则更新值 else if (_table[index].kv.first == key) { _table[index].kv.second = value; return true; } index = (index + 1) % _table.size(); } while (index != start); // 防止无限循环 return false; // 哈希表已满 } // 查找元素 V* find(const K& key) { size_t index = _hash(key); size_t start = index; do { if (_table[index].state == EMPTY) return nullptr; if (_table[index].state == EXIST && _table[index].kv.first == key) return &_table[index].kv.second; index = (index + 1) % _table.size(); } while (index != start); return nullptr; } // 删除元素 bool erase(const K& key) { size_t index = _hash(key); size_t start = index; do { if (_table[index].state == EMPTY) return false; if (_table[index].state == EXIST && _table[index].kv.first == key) { _table[index].state = DELETE; _size--; return true; } index = (index + 1) % _table.size(); } while (index != start); return false; } // 获取元素数量 size_t size() const { return _size; } }; // 测试用例 int main() { HashTable<std::string, int> wordCount; // 插入测试 wordCount.insert("apple", 5); wordCount.insert("banana", 3); wordCount.insert("cherry", 7); // 查找测试 if (auto ptr = wordCount.find("banana")) { std::cout << "banana count: " << *ptr << "\n"; // 输出: 3 } // 更新测试 wordCount.insert("banana", 10); // 更新值 std::cout << "Updated banana count: " << *wordCount.find("banana") << "\n"; // 输出: 10 // 删除测试 wordCount.erase("cherry"); std::cout << "After delete, size: " << wordCount.size() << "\n"; // 输出: 2 // 扩容测试 for (int i = 0; i < 15; ++i) { wordCount.insert("word" + std::to_string(i), i); } std::cout << "After resize, size: " << wordCount.size() << ", table size: " << wordCount.size() * 1.0 / 0.7 << "\n"; return 0; } ``` #### 关键实现细节: 1. **冲突解决**:使用**线性探测法**处理冲突(`index = (index + 1) % size`)[^3] 2. **动态扩容**:当装载因子 ≥ 0.7 时自动扩容为2倍大小[^4] 3. **惰性删除**:删除时只标记状态(`DELETE`),避免数据迁移开销 4. **状态管理**:三种状态区分空槽/有效数据/已删除数据[^4] 5. **哈希函数**:使用`std::hash`作为默认哈希函数[^5] #### 性能特征: - **平均时间复杂度**:$O(1)$(插入/查找/删除) - **最坏情况**:$O(n)$(所有键哈希冲突时) - **空间复杂度**:$O(n)$ > **最佳实践**:当键为自定义类型时,需特化`std::hash`模板[^3]: > ```cpp > struct MyKey { int id; std::string name; }; > namespace std { > template<> struct hash<MyKey> { > size_t operator()(const MyKey& k) const { > return hash<int>()(k.id) ^ (hash<string>()(k.name) << 1); > } > }; > } > ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值