数据结构笔记(六)——散列(Hash Table)之分离链接法(2)

散列函数无法把所有的关键字散列到不同的位置,不可避免的会发生冲突,分离链接法是解决冲突的第一种方法。分离链接法的做法是将散列到同一个地址的关键字保留到一个表中,也就是每个位置分别对应了一个散列到该位置的表。

                                         数据结构笔记(六)——散列(Hash Table)之分离链接法(2)_第1张图片

定义装填因子λ为散列表中元素个数与散列表大小的比值。分离链接法一般会使得表的大小和元素差不多(λ=1),并且表的大小为素数。

如果空间足够的话,我们会使用表头,否则去掉表头也可以。插入时新元素插入到表的最前面,这样既方便又省时,而且一般新插入的元素被再次访问到的几率比较高。具体的实现参考代码。

 

 

HashSep.h

#pragma once
#include
using namespace std;
struct ListNode;
struct HashSep;
#define MINSIZE 5
typedef int ElementType;
typedef ListNode *Position;
typedef Position List;
typedef HashSep *HashTb;

HashTb initialize(int size);
void insert(HashTb ht, ElementType e);
Position find(HashTb ht, ElementType e);
Position findPre(HashTb ht, ElementType e);
void deleteX(HashTb ht, ElementType e);
void destory(HashTb ht);
struct ListNode 
{
	ElementType element;
	Position next;
};
struct HashSep
{
	int table_size;
	List *table;
};
int nextPrime(int x);
int hashFunc(int x, int table_size);

HashSep.cpp

#include"stdafx.h"
#include "HashSep.h"

HashTb initialize(int size)
{
	if (sizetable_size = nextPrime(size);
	ht->table = (List*)malloc(sizeof(List)*ht->table_size);//table为指向tablesize个指针数列的指针,为其分配内存
	/*List head = (List)malloc(sizeof(ListNode)*ht->table_size);
	if (head==nullptr)
	{
		free(ht->table);
		free(ht);
		return nullptr;
	}*/
	if (ht->table==nullptr)
	{
		free(ht);
		cerr << "out of space" << endl;
		return nullptr;
	} 
	for (int i=0;itable_size;++i)//为每个table中的listNode分配内存
	{
		ht->table[i] = (Position)malloc(sizeof(ListNode));
		//ht->table[i] = &head[i];
		if (ht->table[i]==nullptr)
		{
			for (int j=0;jtable[j]);
			}
			free(ht->table);
			free(ht);
			cerr << "out of space" << endl;
			return nullptr;
		}
		else
		{
			ht->table[i]->next = nullptr;
		}
	}
	return ht;
}
void insert(HashTb ht, ElementType e)
{
	if (find(ht,e))
	{
		return;
	}
	Position tmp = (Position)malloc(sizeof(ListNode));
	if (tmp==nullptr)
	{
		cerr << "out of space" << endl;
		return;
	}
	tmp->element = e;
	int pos = hashFunc(e, ht->table_size);
	tmp->next = ht->table[pos]->next;
	ht->table[pos]->next = tmp;
}
Position find(HashTb ht, ElementType e)
{
	int pos = hashFunc(e,ht->table_size);
	Position p = ht->table[pos]->next;
	while (p!=nullptr&&p->element!=e)
	{
		p = p->next;
	}
	return p;
}
Position findPre(HashTb ht, ElementType e)
{
	int pos = hashFunc(e, ht->table_size);
	Position p = ht->table[pos];
	while (p->next != nullptr&&p->next->element != e)
	{
		p = p->next;
	}
	return p;
}
void deleteX(HashTb ht, ElementType e)
{
	Position cur = find(ht, e);
	Position pre = findPre(ht, e);
	pre->next = cur->next;
	cur->next = nullptr;
	free(cur);
}
void destory(HashTb ht)
{
	for (int i=0;itable_size;++i)
	{
		Position p = ht->table[i]->next;
		Position tmp;
		while (p!=nullptr)
		{
			tmp = p;
			p = p->next;
			free(tmp);
		}
	}
	free(ht->table);
	free(ht);
}
int nextPrime(int x)
{
	if (x%2==0)
	{
		x++;//变成奇数
	}
	for(;;x+=2)//偶数不是素数
	{
		bool flag = true;
		for (int i=3;i*i<=x;i+=2)
		{
			if (x%i==0)
			{
				flag = false;
				break;
			}
		}
		if (flag)
		{
			return x;
		}
	}
	return 0;
}
int hashFunc(int x, int table_size)
{
	return x%table_size;
}

test.cpp

#include "stdafx.h"
#include "HashSep.h"
#include
int main()
{
	HashTb ht = initialize(26);
	int input;
	cout << "input: " << endl;
	cin >> input;
	while (input!=-1)
	{
		insert(ht, input);
		cin >> input;
	}
	cout << "table size:" << ht->table_size << endl;
	if (find(ht,33))
	{
		cout << "yes" << endl;
		deleteX(ht, 33);
	}
	else
	{
		cout << "no" << endl;
	}
	destory(ht);
    return 0;
}

结果:

数据结构笔记(六)——散列(Hash Table)之分离链接法(2)_第2张图片

你可能感兴趣的:(数据结构)