HashTable C++ 实现之开放定址法

解决HashTable的冲突的第二种方法叫做开放定址法。开放定址法不需要使用指针,不需要特意的动态分配空间。当发生冲突时此算法会选择其他的空的单元。因此核心问题来了,怎么有效的选择空的单元呢?

  • 算法一:线性探测法 F(i)=i(i为寻址次数)

原理:对HashTable进行插入时,出现Index相同时,我们在原始Index的基础上加F(i)。但是问题又来了,因为F(i)为线性函数,它会连续的Insert元素,因此会出现很多元素的聚集现象,我们也叫做一次聚集。怎么解决呢?往下看哦~

  • 算法二:平方探测法F(i)=F(i-1)+2*i-1  (F(i)=i*i)(i为寻址次数)

原理:对HashTable进行插入时,出现Index相同时,我们在原始Index的基础上加F(i)。但是问题又来了,因为F(i)为平方函数,虽然不会连续的Insert元素,但是会出现二次聚集现象。怎么解决呢?可使用双散列进行,本篇不详细讨论了。

HashTable完整源码如下: 

#include<iostream>
#include<memory>
typedef size_t Index;
typedef std::string ElemType;
const size_t MaxSize = 11;
enum class KindOfEntry{ NoEmpty,Empty,Deleted };
struct HashUnit {
	ElemType      element;
	KindOfEntry   info;  //Lazy Delete
};

struct HashTab {
	size_t            tablesize;
	HashUnit*         arrays;
};

class HashTable {
public:
	HashTable() :hashtable(std::make_unique<HashTab>()) {
		hashtable->tablesize = MaxSize;
		hashtable->arrays = new HashUnit[MaxSize];
		for (int i = 0; i < hashtable->tablesize; ++i)
			hashtable->arrays[i].info = KindOfEntry::Empty;
	};
	~HashTable() {
		if (hashtable->arrays)
			delete[] hashtable->arrays;
	}
public:
	Index Find(const ElemType key)const;
	void Insert(const ElemType key);
	void Delete(const ElemType key);
	void Display()const;
private:
	Index Hash_one(const ElemType key)const;
	Index Hash_two(const ElemType key)const;
	Index Hash_three(const ElemType key)const;
private:
	std::unique_ptr<HashTab>hashtable;
};

Index HashTable::Hash_one(const ElemType key)const {
	size_t hashval = 0;
	int i = 0;
	while (key[i] != '\0') {
		hashval += key[i];
		++i;
	}

	return hashval % hashtable->tablesize;
}

Index HashTable::Hash_two(const ElemType key)const {
	auto hashval = key[0] + key[1] * 27 + key[2] * 27 * 27;
	return hashval % hashtable->tablesize;
}

Index HashTable::Hash_three(const ElemType key)const {
	size_t hashval = 0;
	int i = 0;
	while (key[i] != '\0') {
		hashval = (hashval << 5)/* hashval*32 */ + key[i];
		++i;
	}

	return hashval % hashtable->tablesize;
}

Index HashTable::Find(const ElemType key)const {
	auto index = Hash_three(key);
	size_t count = 0;
	while (hashtable->arrays[index].info != KindOfEntry::Empty && hashtable->arrays[index].element != key) {
		index += 2 * ++count - 1;
		if (index >= hashtable->tablesize)
			index -= hashtable->tablesize;
	}

	return index;
}

void HashTable::Insert(const ElemType key) {
	auto index = Find(key);
	if (hashtable->arrays[index].info != KindOfEntry::NoEmpty) {
		hashtable->arrays[index].info = KindOfEntry::NoEmpty;
		hashtable->arrays[index].element = key;
	}
}

void HashTable::Delete(const ElemType key) {
	auto index = Hash_three(key);
	if (hashtable->arrays[index].info != KindOfEntry::Deleted)
		hashtable->arrays[index].info = KindOfEntry::Deleted;
}

void HashTable::Display()const {
	for (int i = 0; i < hashtable->tablesize; ++i){
		std::cout << "i:" << i << "  " << hashtable->arrays[i].element.c_str() << "     Info:";
		if (hashtable->arrays[i].info == KindOfEntry::Deleted)
			std::cout << "Deleted" << std::endl;
		if (hashtable->arrays[i].info == KindOfEntry::Empty)
			std::cout << "Empty" << std::endl;
		if (hashtable->arrays[i].info == KindOfEntry::NoEmpty)
			std::cout << "NoEmpty" << std::endl;
	}
}

int main(void)
{
	HashTable hash;
	const std::string name = "Jay";
	hash.Insert(name);
	hash.Display();
	std::cout << "Delete a key: Jay" << std::endl;
	hash.Delete(name);
	hash.Display();
	
}


发布了50 篇原创文章 · 获赞 11 · 访问量 4089

猜你喜欢

转载自blog.csdn.net/qq_43145594/article/details/102907529