数据结构实验——链地址法解决冲突构建散列表

1.1 实验内容

假设散列表长为m,散列函数为H(x),用链地址法处理冲突。试编写输入一组关键字并建造散列表的算法。

解决冲突的另一种方法称为开散列方法(opcnhashing,也称为链地址法,separate chaining),在这种方法中,首先按数据元素的关键字用某一个散列函数计算出数据元素的存放位置。通过散列函数计算出来的具有相同地址的数据元素归于同一子集合。每一个子集合也称为一个桶。通常各个桶中的数据元素通过一个单链表链接起来,亦称为同义词子表,所有链表的表头结点组成一个向最。因此,向量的元素个数与可能的桶数相等。桶号为i的同义词子表的表头结点是向量中的第i个元素。

1.2文件结构、开发环境等说明

开发环境版本

VisualStudio 2022

工程文件名

hash_table.sln

头文件个数

3个

源程序文件个数

1个

文件名

文件类型

功能简介

备注

OpenHashTable.h

头文件

开散列表类类模板头文件,包括数据成员及成员函数的声明与定义

Node.h

头文件

结点类模板头文件,包括数据成员及成员函数的声明与定义

Assistance.h

头文件

辅助软件包

text.cpp

源文件

测试文件

1.3 实现技术

1、开散列表类和结点类

OpenHashTable.h文件中声明定义了开散列表类模板,Node.h文件中声明定义了结点类模板

开散列表类中的数据成员有二级Node型指针**ht和除留余数法的除数(在本题中就是表长m)。而结点类中的数据成员有数据域和指针域,数据域存放关键字,指针域存放指向单链表中的下一个结点,在一个单链表中的所有结点用散列函数H(x)计算出来的结果相同(在本题中用除留余数法的函数作为哈希函数)。

开散列表类:

template<class ElemType,class KeyType>
class OpenHashTable
{
protected:
	//数据成员
	Node<ElemType>** ht;//散列表
	int m;//除留余数法的除数
	//辅助函数
	int H(KeyType key) const;//散列函数
public:
	OpenHashTable(int divisor);
	~OpenHashTable();
	OpenHashTable(ElemType v[],int n, int divisor);
	//void show();
};

结点类:

template <class ElemType>
struct Node
{
	// 数据成员:
	ElemType data;				// 数据域
	Node<ElemType>* next;		// 指针域

// 构造函数:
	Node();						// 无参数的构造函数
	Node(ElemType item, Node<ElemType>* link = NULL);	// 已知数数据元素值和指针建立结构
};

2、构造散列表

调用开散列表类中的构造函数来构造开散列表,先for循环将ht[i]都置NULL,表示在ht[i]不存在对应的单链表,即还未存储元素。再通过for循环,依次访问v[]数组中的每一个元素v[i],调用散列函数,将除留余数法的结果赋值给k,再new一个新的Node结点,并用v[i]初始化这个结点的数据域,将ht[k](指向单链表第一个结点的指针)赋值给p的next指针域,并将指向第一个结点的指针ht[k]指向p,至此完成一个结点的插入。后面的结点都采用头插法插入散列表中,直到所有元素都插入完毕。

template<class ElemType, class KeyType>
OpenHashTable<ElemType, KeyType>::OpenHashTable(ElemType v[],int n, int divisor)
{//根据数组v中的元素,divisor为除留余数法的除数构造一个散列表
	int i, k;
	Node<ElemType>* q;//Node型指针
	m = divisor;//赋值除数
	ht = new Node<ElemType>*[m];//分配元素存储空间

	for (i = 0; i < m; i++)
		ht[i] = NULL;

	for (i = 0; i < n; i++)
	{
		k = H(v[i]);
		q = new Node<ElemType>(v[i]);
		q->next = ht[k];
		ht[k] = q; 
	}
……
}

3、显示散列表

遍历整个散列表,将散列表形象地显示出来。

template<class ElemType, class KeyType>
OpenHashTable<ElemType, KeyType>::OpenHashTable(ElemType v[],int n, int divisor)
{//根据数组v中的元素,divisor为除留余数法的除数构造一个散列表
	……
	for (i = 0; i < n; i++)
	{
		cout << i << ":   ";
		if (ht[i] == NULL)
			cout << endl;
		else
		{
			//cout << ht[i]->data << " --> ";
			Node<ElemType>* p;
			p = ht[i];
			while (p != NULL)
			{
				cout << p->data << " --> ";
				p = p->next;
			}
			cout << "NULL"<<endl;
		}
	}
}

1.4 测试结果

1.4.1.1测试实例

int elem[] = { 19, 14, 23, 1, 68, 20, 84, 27, 55, 11, 10, 79 };
OpenHashTable<int, int>ht(elem, 12, 12);

1.4.1.2测试结果

1.4.1.2测试实例

int elem[] = { 22,76,53,49,88,2,36,75,45,42,25,29,20,38,41,43,70,73,66,63,64,69,100,121,136,532,786 };
OpenHashTable<int, int>ht(elem, 12, 12);

1.4.1.2测试结果

完整代码可看资源区

创作不易~麻烦点个赞~~谢谢大家~~~

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值