哈希表解决冲突法(二次探测)

故数据存储下标为

伪代码:

1. //index=_HashFunc(key);

//++i;

//index+=(2*i-1);

size_t _HashFunc(const K& key)

{

return key%_capacity;

}

2.//index=_HashFunc(key,++i);

size_t _HashFunc(const K& key,size_t i)

{

return (key+i*i)%_capacity;

}

#pragma once
#include<iostream>
using namespace std;

enum Status
{
	EXIST,
	EMPTY,
	DELETE
};
template<class K>
class HashTable
{
public:
	HashTable(int capacity)
		:_table(new K[capacity])
		, _size(0)
		, _capacity(capacity)
		, _statu(new Status[capacity])
	{
		memset(_table, 0, sizeof(K)*capacity);
		for (int i = 0; i < capacity; ++i)
		{
			_statu[i] = EMPTY;
		}
	}
	HashTable(const HashTable& hb)
		:_table(new K[hb._capacity])
		, _capacity(hb._capacity)
		, _size(0)
		, _statu(new Status[_capacity])
	{
		memset(_table, 0, sizeof(K)*_capacity);
		for (int i = 0; i < _capacity; ++i)
		{
			_statu[i] = EMPTY;
		}

		for (int i = 0; i < _capacity; ++i)
		{
			if (hb._statu[i] == EXIST)
			{
				this->Insert(hb._table[i]);
			}
		}
	}
	HashTable& operator=(HashTable ht)
	{
		this->_Swap(ht);
		return *this;
	}
	~HashTable()
	{
		if (_table)
			delete[] _table;
		if (_statu)
			delete[] _statu;
		_capacity = _size = 0;
	}
	bool Insert(const K& key)
	{
		if (_size * 10 / _capacity >= 7)//负载因子最好在0.7到0.8
		{
			size_t newCapacity = _capacity * 2;
			HashTable<K> tmp(newCapacity);
			for (int i = 0; i < _capacity; ++i)
			{
				if (_statu[i] == EXIST)
				{
					tmp.Insert(_table[i]);
				}
			}
			this->_Swap(tmp);//自定义
		}

		int i = 0;
		size_t index = _HashFunc(key,i);
		size_t begin = index;
		do
		{
			if (_statu[index] == EMPTY||_statu[index]==DELETE)
				break;
			if (_statu[index] == EXIST&&_table[index] == key)
			{
				return false;
			}
			index = _HashFunc(key, ++i);
			if (index == _capacity)
				index = 0;
		} while (begin!=index);
		if (_statu[index] == EXIST)
			return false;
		_table[index] = key;
		_statu[index] = EXIST;
		++_size;
		return true;
	}
	bool Find(const K& key)
	{
		int i = 0;
		size_t index = _HashFunc(key,i);
		while (_statu[index] != EMPTY)
		{
			if (_statu[index] == EXIST&&_table[index] == key)
			{
				return true;
			}
			index=_HashFunc(key,++i);
			if (++index == _capacity)
				index = 0;
		}
		return false;
	}
	//懒删除
	bool  Remove(const K& key)
	{
		int i = 0;
		size_t index = _HashFunc(key,0);
		while (_statu[index] != EMPTY)
		{
			if (_statu[index] == EXIST&&_table[index] == key)
			{
				_statu[index] = DELETE;
				--_size;
				return true;
			}
			index = _HashFunc(key,++i);
			if (++index == _capacity)
				index = 0;
		}
		return false;
	}
	void Print()
	{
		for (int i = 0; i < _capacity; ++i)
		{
			printf("%d:%d-->", _table[i], _statu[i]);
		}
		cout << endl;
	}
protected:
	void _Swap(HashTable& ht)
	{
		swap(_table, ht._table);
		swap(_size, ht._size);
		swap(_capacity, ht._capacity);
		swap(_statu, ht._statu);
	}
	size_t _HashFunc(const K& key,size_t i)
	{
		return (key+i*i)%_capacity;
	}
protected:
	K* _table;
	size_t _size;
	size_t _capacity;
	Status* _statu;
};
void Test2()
{
	HashTable<int> ht(10);
	ht.Insert(89);
	ht.Insert(18);
	ht.Insert(49);
	ht.Insert(58);
	ht.Insert(9);
	ht.Print();

	HashTable<int> hb(10);
	hb.Insert(1);
	hb.Insert(2);
	hb.Insert(3);
	hb.Insert(4);
	hb.Insert(9);
	hb.Print();

	HashTable<int> h(ht);
	h.Print();

	h = hb;
	h.Print();
}
时间: 2024-10-27 09:12:02

哈希表解决冲突法(二次探测)的相关文章

哈希表解决冲突链地址java

package ch17; import java.math.BigInteger; public class HashTable { private LinkList[] arr; /** * 默认的构造方法 */ public HashTable() { arr = new LinkList[100]; } /** * 指定数组初始化大小 */ public HashTable(int maxSize) { arr = new LinkList[maxSize]; } /** * 插入数据

【算法与数据结构】哈希表-链地址法

哈希表的链地址法来解决冲突问题 将所有关键字为同义词的记录存储在同一个线性链表中,假设某哈希函数产生的哈希地址在区间[0, m - 1]上,则设立一个至振兴向量 Chain  ChainHash[m]; 数据结构 //链表结点 typedef struct _tagNode { int data; //元素值(关键字) struct _tagNode* next; //下一个结点 }Node, *PNode; //哈希表结点 typedef struct _tagHashTable { //这里

哈希表之三冲突解决

前的部分分析了,哈希表中的冲突时难以避免的,冲突是很正常的,所以就要知道如何解决冲突. 我觉得冲突是有两种解决的方法: 1.横向的解决 2.纵向的解决 所谓横向解决:指的是对冲突的键,会在哈希表上另外找一个位置来安放它: 纵向解决是指:在冲突的键上会有一个线性链表,来存储冲突的元素. "处理冲突"就是为该关键字的记录找到一个"空"的哈希地址. 在处理冲突时,可能得到一个地址序列: 在处理冲突的时候,如果得到另一个哈希地址H1让然发生冲突,则会继续计算下一个地址H2,

哈希表和冲突解决

1.散列表 散列表(Hash table,也叫哈希表),是根据键(Key)而直接访问在内存存储位置的数据结构.也就是说,它通过计算一个关于键值的函数,将所需查询的数据映射到表中一个位置来访问记录,这加快了查找速度.这个映射函数称做散列函数,存放记录的数组称做散列表. 2.散列函数 散列函数能使对一个数据序列的访问过程更加迅速有效,通过散列函数,数据元素将被更快定位. (1). 直接定址法:取关键字或关键字的某个线性函数值为散列地址.即{ hash(k)=k} 或{ hash(k)=a*k+b}

哈希表(开链法)

纯代码 #pragma once #include <iostream> #include <vector> using namespace std; struct __HashFuncString { size_t operator()(const string &key) { size_t hash = 0; for (size_t i = 0; i < key.size(); ++i) { hash += key[i]; } return hash; } };

哈希表之拉链法

前段时间理解了一下所谓的哈希表,一直以来在小博印象中哈希表是深奥的,是高大上的,但是接触原理以及看了一份demo之后我就觉得哈希表也就那样吧,接下来我把小博自己的理解尽量用最直白的语句来解释下~~~ ---------------------------------------------------------我是分界线,没错,很丑------------------------------------------------------------------ 首先什么是哈希表??? 散列表

哈希表解决字符串问题

题目5:无重复字符的最长子串 给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度. 示例 1: 输入: "abcabcbb" 输出: 3 解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3. 示例 2: 输入: "bbbbb" 输出: 1 解释: 因为无重复字符的最长子串是 "b",所以其长度为 1. 示例 3: 输入: "pwwkew" 输出: 3 解释: 因为无重复字符的最长子

《Java数据结构和算法》- 哈希表

Q: 如何快速地存取员工的信息? A: 假设现在要写一个程序,存取一个公司的员工记录,这个小公司大约有1000个员工,每个员工记录需要1024个字节的存储空间,因此整个数据库的大小约为1MB.一般的计算机内存都可以满足. 为了尽可能地存取每个员工的记录,使用工号从1(公司创业者)到1000(最近雇佣的工人).将工号作为关键字(事实上,用其他作为关键字完全没有必要).即使员工离职不在公司,他们的记录也是要保存在数据库中以供参考,在这种情况下需要使用什么数据结构呢? A: 一种可能使用数组,每个员工

哈希表——线性探测法、链地址法、查找成功、查找不成功的平均长度

一.哈希表 1.概念 哈希表(Hash Table)也叫散列表,是根据关键码值(Key Value)而直接进行访问的数据结构.它通过把关键码值映射到哈希表中的一个位置来访问记录,以加快查找的速度.这个映射函数就做散列函数,存放记录的数组叫做散列表. 2.散列存储的基本思路 以数据中每个元素的关键字K为自变量,通过散列函数H(k)计算出函数值,以该函数值作为一块连续存储空间的的单元地址,将该元素存储到函数值对应的单元中. 3.哈希表查找的时间复杂度 哈希表存储的是键值对,其查找的时间复杂度与元素数