hash_map C++实现

本文介绍了使用C++实现hash_map的详细步骤,包括结构体定义、哈希函数设计、插入、查找、删除等操作。通过自定义MyList类,实现了HashMap的创建、键值对的增删查改功能,并提供了相关辅助方法展示HashMap信息。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

#include<iostream.h>
#include<stdlib.h>

const int MapSize = 1024;
struct hashmap_ele
{
	int key; //key
	int value; //value
	int in_use; //开始时位置上无元素,未被占用
	hashmap_ele * multis; //hash地址相同的值,通过索引链接他
};

struct hash_map
{
	int table_size; //总大小
	int size; //当前的大小
	hashmap_ele * date; //数据的链接
};

hash_map * map_head;

//MyList类
class MyList
{
public:
	hash_map * CreateHashMap(); //创建HashMap
	int GetPosition(hash_map *m, int key); //计算键值对存储的位置
	bool IsInUse(hash_map *m, int key); //判断位置上是否已经有元素
	int IsKeyExists(hash_map *m, int key); //判断map中是否已经存在该键
	void SetKey(int key, int val); //加入键值对
	void DisEntry(hash_map *m); //打印所有的键值对
	void DeleteKey(int key); //删除指定的键值对
	int SearchKey(int key); //搜索出与指定键对应的值
	int GetMapSize();
	void ShowInfo(hash_map * m); //输出map的相关信息
};

//创建HashMap
hash_map * MyList::CreateHashMap()
{
	hash_map *m;
	m = (hash_map *)malloc(sizeof(hash_map)); //创建HashMap,分配空间
	m->date = (hashmap_ele *)calloc(MapSize, sizeof(hashmap_ele)); //为HashMap的数据分配空间,初始空间为1024
	m->table_size = MapSize; //指定总的大小
	m->size = 0; //指定当前的大小
    
	return m;
}

//得到key的存储位置
int MyList::GetPosition(hash_map *m, int key) //得到键值对存储的位置
{
	key += (key << 12);
	key ^= (key >> 22);
	key += (key << 4);
	key ^= (key << 9);
	key += (key << 10);
	key ^= (key >> 2);
	key += (key << 7);
	key ^= (key >>12);
	key = (key >> 3) * 2654435761;
	key %=m->table_size;
	if(key < 0)
		key = -key;
	return key;
}
/*
 判断第一个位置上是否已经有元素
 */
bool MyList::IsInUse(hash_map *m, int key)
{
	int curr;
	curr = GetPosition(m, key);
    
	if(m->date[curr].multis == NULL) //第一个位置未被占用
		return false;
	else //第一个位置被占用
		return true;
}

/*
 判断key是否已在HashMap中存在
 */
int MyList::IsKeyExists(hash_map *m, int key)
{
	int pos;
	int flag = 0;
	int record = 1; //记录节点在链中的那个位置
	hashmap_ele * e;
	pos = GetPosition(m, key);
	if(m->table_size == m->size){
		int size = MapSize;
		realloc(m, size+=size);
	}
	if(!IsInUse(m, key)) //第一个位置没有被占用,map中没有该键
	{
		return 0;
	}else{  //第一个位置被占用,存在一个键,检查他的hashmap_ele * multis指针
		if(m->date[pos].multis->key == key) //第一个位置上元素的键就是,已经存在,返回true;
			return record;
		else{ //第一个键不是,要向下检查
			if((e = m->date[pos].multis->multis) != NULL) //还有其他的元素
			{
				do{
					++record;
					if(e->key == key){
						flag = 1;
						break;
					}
				}while((e = e->multis) != NULL);
			}
			else //键不相等,并且hashmap_ele * multis指针为空,不存在该键
				return 0;
            
			if(flag == 1)
				return record;
			else
				return 0;
		}
	}
}

/*
 向HashMap中插入一键值对
 */
void MyList::SetKey(int key, int val)
{
	hash_map * m; //hash_map 的变量
	hashmap_ele *e, *add; //hashmap_ele 的变量
	int pos;
    
	add = (hashmap_ele *)malloc(sizeof(hashmap_ele));
	add->key = key;
	add->value = val;
	add->in_use = 1;
	add->multis = NULL;
    
	m = map_head;
	pos = GetPosition(m, key);
	
	if(m->date == NULL) //HashMap为空
		cout<<"The hashmap is not create !"<<endl;
	else{
		if(!IsKeyExists(map_head, key)) // map中没有该键
		{
			e = m->date[pos].multis;  //指向第一个位置,不管第一个位置占用还是不占用
			m->size++;
			if(!IsInUse(map_head, key)) //第一个位置未被占用
			{
				m->date[pos].multis = add;
			}
			else{ //第一个位置被占用
				while(e->multis != NULL)
				{
					e = e->multis;
				}
				e->multis = add;
			}
		}else{ //map中该键值已经存在
			cout<<"该键已经在map中存在,插入失败!"<<endl;
		}
	}
}

/*
 打印出HashMap中的键值对
 */
void MyList::DisEntry(hash_map * m)
{
	hashmap_ele * e1, * e2;
	e1 = m->date; //e1指向了存储位置
	for(int i = 0; i < m->table_size; i++)
	{
		if((e1 + i)->multis != NULL)
		{
			e2 = (e1 + i)->multis; //e2指向了第一个位置
			do{
				cout<<e2->key<<"-->"<<e2->value<<endl;
				e2 = e2->multis;
			}while(e2 != NULL);
		}
	}
}

/*
 删除指定的key
 */
void MyList::DeleteKey(int key)
{
	int record;
	int pos;
	hashmap_ele * e, *efree;
	hash_map *m;
	m = map_head;
    
	record = IsKeyExists(m, key);
	pos = GetPosition(m, key);
	if(!record){
		cout<<"map中没有指定的key值 !"<<endl;
	}else{
		e = &(m->date[pos]); //将存储位置赋值给e
		for(int i = 1; i <= record -1; i++)
		{
			e = e->multis;
		}
		efree = e->multis->multis;
		e->multis = NULL; //将位置指向NULL,不再指向删除的节点
		--(m->size); //将map的当前键值对减1
		free(efree); //释放删除节点的内存
		cout<<"删除键值成功!"<<endl;
	}
}

/*
 获取键为key的值
 */
int MyList::SearchKey(int key)
{
	int record;
	int pos;
	hashmap_ele *e;
	hash_map *m;
    
	m = map_head;
	pos = GetPosition(m, key);
	record = IsKeyExists(m, key);
	if(!record){
		cout<<"map中不存在此键!"<<endl;
		return 0;
	}else{
		e = &(m->date[pos]); //将存储位置赋值给e
		for(int i = 1; i <= record; i++)
		{
			e = e->multis;
		}
		return e->value;
	}
}

/*
 获取map当前有多少键值对
 */
int MyList::GetMapSize()
{
	return map_head->size;
}

/*
 获取map中的当前信息
 */
void MyList::ShowInfo(hash_map * m)
{
	cout<<"当前map中的键值对个数:"<<m->size<<endl;//输出当前map中的键值对个数
	cout<<"当前map中的键值对:"<<endl;
	DisEntry(m); //打印出当前map中的键值对
}


/*
 主函数
 */
int main(void)
{
	MyList myList;
	int addKey;
	int addValue;
	int delKey;
	int searchKey;
	int searchValue;
	/*
     创建HashMap
     */
	cout<<"创建一个新map:"<<endl;
	map_head = myList.CreateHashMap();
	cout<<"map的总大小:"<<map_head->table_size<<endl;
	cout<<"map的当前大小(当前map中的键值对):"<<map_head->size<<endl;
	cout<<"-------------------------------------------"<<endl;
    
	/*
     增加一对键值到哈希表中
     */
	cout<<"插入两个键值对(1025, 23)(99999,23):"<<endl;
	myList.SetKey(1025, 23);
	myList.SetKey(99999, 23);
	myList.ShowInfo(map_head);//输出map的相关信息
    
	cout<<"输入所插入的键(数值类型):"<<endl;
	cin>>addKey;
	cout<<"输入所插入的值(数值类型):"<<endl;
	cin>>addValue;
	myList.SetKey(addKey, addValue);
	cout<<"已插入键值对:("<<addKey<<","<<addValue<<")"<<endl;
	myList.ShowInfo(map_head);//输出map的相关信息
	cout<<"-------------------------------------------"<<endl;
    
	/*
     删除键为key的单元
     */
	cout<<"请输入要删除的键:"<<endl;
	cin>>delKey;
	myList.DeleteKey(delKey); //删除指定的delKey
	myList.ShowInfo(map_head);//输出map的相关信息
	cout<<"-------------------------------------------"<<endl;
	
	/*
     获取与指定键对应的值
     */
	cout<<"请输入要获取的键:"<<endl;
	cin>>searchKey;
	searchValue = myList.SearchKey(searchKey);
	cout<<"您要搜寻的键的值为:"<<searchValue<<endl;
	cout<<"-------------------------------------------"<<endl;
    
	/*
     获取map当前有多少键值对
     */
	cout<<"map中当前键值对的个数为:"<<myList.GetMapSize()<<endl;
	
	return 0;
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值