c++哈希表

哈希表

一、概念

1.散列表,最有用的基本数据结构之一。是根据关键码的值直接进行访问的数据结构,散列表的实现常常叫做散列(hasing)

2.散列技术是在通过记录的存储位置和它的关键字之间建立一个确定的对应关系 f ,使得每个关键字 key 都对应一个存储位置 f(key)。

3.而2中的f就是所谓的哈希函数。

二、散列函数的构造方法

直接定址法

就是通过数据本身产生线性的映射关系

f(key) = a*key+b

数字分析法

分析关键字,选取部分或者对部分位移、叠加。如学号、班号等。

折叠法

将关键字从左到右分割成位数相等的几部分,然后叠加求和,并按散列表表长,取后几位作为散列地址

除法散列法

f(k) = k mod p (p <= m)

乘法散列法

  • 用关键字 k 乘上常数 A(0 < A < 1),并提取 k A 的小数部分
  • 用 m 乘以这个值,再向下取整

f (k) = ⌊ m(kA mod 1) ⌋

平方取中法

f (k) = (k^2/10)%1000 (假如 k^2为5位抽其中3位)

随机数法

f (k) = random

三、散列冲突

四、c++示例代码1

struct MyNode//结点构建
{
	int data;//数据域
	MyNode * pNext;//指针域
};
//主表结构 - 指针数组
struct HashTable//哈希值域 0 - 9
{
	MyNode * val[10];
};
//创建函数 - 构造函数
HashTable * createHashTable()
{
	HashTable * pHead = new HashTable;
	memset(pHead, 0, sizeof(HashTable));
	return pHead;
}
//哈希函数
int GetIndex(int data)
{
	//平方取中
	/*int num = data*data;
	num = (num / 10) % 1000; //取中间三位
	return num;*/
	//取余
	return data % 10;//去个位上的数
}
//功能1 - 数据的插入
bool insertHashTable(HashTable * pHash, int const& val)
{
	//1、表是否存在
	if (nullptr == pHash)
		return false;
	//2、主表存在,判断分表是否存在
	//2.1、创建遍历指针
	MyNode * pNode = pHash->val[GetIndex(val)];//通过分表的头指针判断
	if (nullptr == pNode)
	{
		//2.2、没有分表 - 空链表做插入
		pHash->val[GetIndex(val)] = new MyNode;
		pHash->val[GetIndex(val)]->data = val;
		pHash->val[GetIndex(val)]->pNext = nullptr;
	}
	else
	{
		//2.3存在分表 - 尾插
		while (pNode->pNext)//下一个为空指针就退出
		{
			pNode = pNode->pNext;//往下遍历
		}
		//找到了
		pNode->pNext = new MyNode;
		pNode->pNext->data = val;
		pNode->pNext->pNext = nullptr;
	}
	return true;
}
//查找 - 返回结点
MyNode * findDataInHash(HashTable * pHash, int const& findData)
{
	//1、有无主表
	if (nullptr == pHash)
		return nullptr;
	//2、准备遍历指针,遍历各个分表
	MyNode * pNode;
	pNode = pHash->val[GetIndex(findData)];//分表的表头
	if (pNode == nullptr)
		return nullptr;
	//3、分表存在内容 往下找
	while (pNode)
	{
		if (pNode->data == findData)
		{
			//3.1、找到了
			return pNode;
		}
		else
		{
			//3.2、继续找
			pNode = pNode->pNext;
		}
	}
	//3.3、循环结束 还没有返回出去 没找到
	return nullptr;
}
//删除
bool delDataFromHash(HashTable * pHash, int const& delData)
{
	//1、表是否存在
	if (nullptr == pHash)
		return false;
	//2、主表存在,找到该元素
	MyNode * pNode;//找的工具
	pNode = findDataInHash(pHash, delData);
	if (nullptr == pNode) //未找到
		return false;
	//3、找到了 删除它
	//3.1、获取表头
	MyNode * pHead = pHash->val[GetIndex(delData)];//指到分表表头
	if (pNode == pHead)//数据是否在表头位置
	{
		//3.2、头删
		pHash->val[GetIndex(delData)] = pHash->val[GetIndex(delData)]->pNext;
		//delete pNode;
	}
	else
	{
		//3.3、中间删除
		while (pHead->pNext!=pNode)
		{
			pHead = pHead->pNext;
		}
		//找到了上一个结点
		pHead->pNext = pHead->pNext->pNext;//写法1
		//pHead->pNext = pNode->pNext;//写法2
		//delete pNode;
	}
	//3.4、删除pNode 并返回
	delete pNode;
	pNode = nullptr;
	return true;
}
//销毁整个表
void clearHashTable(HashTable *& pHash)//传入的才是指针的本身
{
	//1、判断主表
	if (nullptr == pHash)
		return;
	//2、存在主表 
	//2.1、需要两个指针配合
	MyNode *pNode, *pHead;
	//2.2、清理各个分表
	for (int i = 0; i < 10; ++i)
	{
		if ((pHead = pHash->val[i]) != nullptr)
		{
			while (pHead)
			{
				//定位到第一个结点
				pNode = pHead;
				//头删
				pHead = pHead->pNext;
				delete pNode;
			}
		}
		//pHash->val[i] = nullptr;
	}
	//3、循环结束 分表被删完了 删主表
	delete pHash;
	pHash = nullptr;
}

五、c++哈希表使用方法

1.建立基本数据类型的哈希表

unordered_map<int,int> m; //,

2.向哈希表中添加元素

1).insert 函数

m.insert(pair<int,int>(1, 10));
m.insert(pair<int,int>(2, 20));

2)用数组方法直接添加

m[3]=30;
m[4]=40;

3.成员函数

begin(),end()函数
m.begin() //指向哈希表的第一个容器
m.end()  //指向哈希表的最后一个容器,实则超出了哈希表的范围,为空
find()查找函数
m.find(2)  //查找key为2的键值对是否存在 ,若没找到则返回m.end()
if(m.find(2)!=m.end()) //判断找到了key为2的键值对
count() 查找函数

查找哈希表中key为3的键值对,返回其数量,为1,则找到,若没找到则返回0

m.count(3)  //返回 1
m.count(5)   //返回0
size()函数
m.size()   //返回哈希表的大小
empty()函数
m.empty()  //判断哈希表是否为空,返回值为true/false
clear()函数
m.clear()  //清空哈希表
swap()函数

交换两个哈希表中的元素,整个哈希表的键值对全部都交换过去

unordered_map<int,int> m1;
unordered_map<int,int> m2;
m1.swap(m2);
swap(m1,m2);

4.哈希表的遍历

第一种遍历
unordered_map<int, int> count;
for (auto p : count) {
	int front = p.first;   //key
    int end = p.second;   //value
}
第二种遍历
unordered_map<int, int> count;
for(auto it=m.begin();it!=m.end();it++)
{
    int front = it->first;   //key
    int end = it->second;   //value
}

你可能感兴趣的:(c++,散列表,数据结构)