深圳大学计软《数据结构》实验14--哈希表与排序1

问题 A: DS哈希查找—线性探测再散列

题目描述

定义哈希函数为H(key) = key%11,输入表长(大于、等于11)。输入关键字集合,用线性探测再散列构建哈希表,并查找给定关键字。

–程序要求–
若使用C++只能include一个头文件iostream;若使用C语言只能include一个头文件stdio
程序中若include多过一个头文件,不看代码,作0分处理
不允许使用第三方对象或函数实现本题的要求

输入

测试次数t

每组测试数据为:

哈希表长m、关键字个数n

n个关键字

查找次数k

k个待查关键字

输出

对每组测试数据,输出以下信息:

构造的哈希表信息,数组中没有关键字的位置输出NULL

对k个待查关键字,分别输出:0或1(0—不成功,1—成功)、比较次数、查找成功的位置(从1开始)

样例输入

1
12 10
22 19 21 8 9 30 33 4 15 14
4
22
56
30
17

样例输出

22 30 33 14 4 15 NULL NULL 19 8 21 9
1 1 1
0 6
1 6 2
0 1

AC代码

#include<iostream>
using namespace std;

class HashList {
	int* list;
	int length;
public:
	HashList() {
		int  n;
		cin >> length >> n;
		list = new int[length];
		for (int i = 0; i < length; i++)
			list[i] = 0;
		for (int i = 0; i < n; i++) {
			int key;
			cin >> key;
			Hash(key);
		}
	}

	void Hash(int key) {
		int key1 = key % 11;
		for (int i = 0; i < length; i++) {
			int temp = (key1 + i) % length;
			if (list[temp])
				continue;
			list[temp] = key;
			break;
		}
	}

	void print() {
		for (int i = 0; i < length; i++) {
			if (i)
				cout << " ";
			if (list[i])
				cout << list[i];
			else cout << "NULL";
		}
		cout << endl;
	}

	void find(int key) {
		int cnt = 0, index = -1;
		bool ok = 0;

		int key1 = key % 11;
		for (int i = 0; i < length; i++)
		{
			cnt++;
			int temp = (key1 + i) % length;

			if (!list[temp])
				break;
			if (list[temp] == key)
			{
				ok = 1;
				index = temp;
				break;
			}
		}
		if (ok)
			cout << ok << " " << cnt << " " << index + 1 << endl;
		else
			cout << ok << " " << cnt << endl;
	}
	~HashList()
	{
		delete[]list;
	}
};

int main() {
	int n;
	cin >> n;
	while (n--)
	{
		HashList h;
		int n1;
		h.print();
		cin >> n1;
		while (n1--)
		{
			int key;
			cin >> key;
			h.find(key);
		}
	}
	return 0;
}

问题 B: DS哈希查找—二次探测再散列

题目描述

定义哈希函数为H(key) = key%11。输入表长(大于、等于11),输入关键字集合,用二次探测再散列构建哈希表,并查找给定关键字。

输入

测试次数t

每组测试数据格式如下:

哈希表长m、关键字个数n

n个关键字

查找次数k

k个待查关键字

输出

对每组测试数据,输出以下信息:

构造的哈希表信息,数组中没有关键字的位置输出NULL

对k个待查关键字,分别输出:

0或1(0—不成功,1—成功)、比较次数、查找成功的位置(从1开始)

样例输入

1
12 10
22 19 21 8 9 30 33 4 41 13
4
22
15
30
41

样例输出

22 9 13 NULL 4 41 NULL 30 19 8 21 33
1 1 1
0 3
1 3 8
1 6 6

AC代码

#include<iostream>
#include<cmath>
using namespace std;

class HashList {
	int* list;
	int length;

	int* dis;

	void Hash(int key) {
		int key1 = key % 11;
		for (int i = 0; i < length; i++) {
			int temp = (key1 + dis[i] + length) % length;
			if (list[temp])
				continue;
			list[temp] = key;
			break;
		}
	}


public:
	HashList() {
		int  n;
		cin >> length >> n;
		list = new int[length];
		dis = new int[length];

		dis[0] = 0;
		for (int i = 1; i < length; i++)
		{
			if (i % 2)
				dis[i] = pow((i + 1) / 2, 2);
			else
				dis[i] = -dis[i - 1];
		}


		for (int i = 0; i < length; i++)
			list[i] = 0;


		for (int i = 0; i < n; i++) {
			int key;
			cin >> key;
			Hash(key);
		}
	}

	void print() {
		for (int i = 0; i < length; i++) {
			if (i)
				cout << " ";
			if (list[i])
				cout << list[i];
			else cout << "NULL";
		}
		cout << endl;
	}

	void find(int key) {
		int cnt = 0, index = -1;
		bool ok = 0;

		int key1 = key % 11;
		for (int i = 0; i < length; i++)
		{
			cnt++;
			int temp = (key1 + dis[i] + length) % length;

			if (!list[temp])
				break;
			if (list[temp] == key)
			{
				ok = 1;
				index = temp;
				break;
			}
		}
		if (ok)
			cout << ok << " " << cnt << " " << index + 1 << endl;
		else
			cout << ok << " " << cnt << endl;
	}
	~HashList()
	{
		delete[]list;
		delete[]dis;
	}
};

int main() {
	int n;
	cin >> n;
	while (n--)
	{
		HashList h;
		int n1;
		h.print();
		cin >> n1;
		while (n1--)
		{
			int key;
			cin >> key;
			h.find(key);
		}
	}
	return 0;
}

问题 C: DS哈希查找–链地址法

题目描述

给出一个数据序列,建立哈希表,采用求余法作为哈希函数,模数为11,哈希冲突用链地址法和表头插入

如果首次查找失败,就把数据插入到相应的位置中

实现哈希查找功能

输入

第一行输入n,表示有n个数据
第二行输入n个数据,都是自然数且互不相同,数据之间用空格隔开
第三行输入t,表示要查找t个数据
从第四行起,每行输入一个要查找的数据,都是正整数

输出

每行输出对应数据的查找结果

样例输入

6
11 23 39 48 75 62
6
39
52
52
63
63
52

样例输出

6 1
error
8 1
error
8 1
8 2

提示

注意,当两次输入要相同的查找数据,如果第一次查找不成功就会执行插入,那么第二次查找必然成功,且查找次数为1次(因为做表头插入)

例如示例数据中输入两次52,第一次查找失败就把52插入到位置8,第二次查找就成功了,所以第一次输出error,第二次就输出8 1

为什么第三次输入52会输出8 2

AC代码

#include<iostream>
#include<list>
using namespace std;

class HashList {
	list<int>* l;
public:
	HashList() {
		int  n;
		cin >> n;
		l = new list<int>[11];
		for (int i = 0; i < n; i++) {
			int key;
			cin >> key;
			hash(key);
		}
	}


	void hash(int key) {
		int key1 = key % 11;
		l[key1].push_front(key);
	}

	void find(int key) {
		int key1 = key % 11;
		int cnt = 0;
		bool ok = 0;
		for (auto& it : l[key1])
		{
			cnt++;
			if (it != key)
				continue;
			ok = 1;
			break;
		}
		if (ok)
			printf("%d %d\n", key1, cnt);
		else {
			puts("error");
			l[key1].push_front(key);
		}
	}

	~HashList()
	{
		delete[]l;
	}
};

int main() {
		HashList h;
		int n1;
		cin >> n1;
		while (n1--)
		{
			int key;
			cin >> key;
			h.find(key);
		}
	return 0;
}

问题 D: DS哈希查找与增补

题目描述

给出一个数据序列,建立哈希表,采用求余法作为哈希函数,模数为11,哈希冲突用链地址法和表尾插入

如果首次查找失败,就把数据插入到相应的位置中

实现哈希查找与增补功能

输入

第一行输入n,表示有n个数据
第二行输入n个数据,都是自然数且互不相同,数据之间用空格隔开
第三行输入t,表示要查找t个数据
从第四行起,每行输入一个要查找的数据,都是正整数

输出

每行输出对应数据的查找结果,每个结果表示为数据所在位置[0,11)和查找次数,中间用空格分开

样例输入

6
11 23 39 48 75 62
6
39
52
52
63
63
52

样例输出

6 1
error
8 1
error
8 2
8 1

AC代码

#include<iostream>
#include<list>
using namespace std;

class HashList {
	list<int>* l;
public:
	HashList() {
		int  n;
		cin >> n;
		l = new list<int>[11];
		for (int i = 0; i < n; i++) {
			int key;
			cin >> key;
			hash(key);
		}
	}


	void hash(int key) {
		int key1 = key % 11;
		//l[key1].push_front(key);
		l[key1].push_back(key);
	}

	void find(int key) {
		int key1 = key % 11;
		int cnt = 0;
		bool ok = 0;
		for (auto& it : l[key1])
		{
			cnt++;
			if (it != key)
				continue;
			ok = 1;
			break;
		}
		if (ok)
			printf("%d %d\n", key1, cnt);
		else {
			puts("error");
			//l[key1].push_front(key);
			l[key1].push_back(key);
		}
	}

	~HashList()
	{
		delete[]l;
	}
};

int main() {
		HashList h;
		int n1;
		cin >> n1;
		while (n1--)
		{
			int key;
			cin >> key;
			h.find(key);
		}
	return 0;
}

问题 E: DS内排—直插排序

题目描述

给定一组数据,使用直插排序完成数据的升序排序。

–程序要求–
若使用C++只能include一个头文件iostream;若使用C语言只能include一个头文件stdio
程序中若include多过一个头文件,不看代码,作0分处理
不允许使用第三方对象或函数实现本题的要求

输入

数据个数n,n个数据

输出

直插排序的每一趟排序结果

样例输入

7 34 23 677 2 1 453 3

样例输出

23 34 677 2 1 453 3
23 34 677 2 1 453 3
2 23 34 677 1 453 3
1 2 23 34 677 453 3
1 2 23 34 453 677 3
1 2 3 23 34 453 677

AC代码

#include<iostream>
using namespace std;

//西天还有些儿残霞,教我如何不想她。
void InsertSort(int* p, int num) {
	int j;
	for (int i = 1; i < num; i++)
	{
		int temp = p[i];
		for (j = i - 1; j >= 0; j--)
			if (temp < p[j])
				p[j + 1] = p[j];
			else break;
		p[j + 1] = temp;
		for (int i = 0; i < num; i++)
		{
			if (i)
				cout << " ";
			cout << p[i];
		}
		cout << endl;
	}
}

int main() {
	int* p, num;
	cin >> num;
	p = new int[num];
	for (int i = 0; i < num; i++)
		cin >> p[i];
	InsertSort(p, num);
	delete[]p;
	return 0;
}

问题 F: DS单链表–类实现

题目描述
用C++语言和类实现单链表,含头结点

属性包括:data数据域、next指针域

操作包括:插入、删除、查找

注意:单链表不是数组,所以位置从1开始对应首结点,头结点不放数据

类定义参考
在这里插入图片描述

输入

n
第1行先输入n表示有n个数据,接着输入n个数据
第2行输入要插入的位置和新数据
第3行输入要插入的位置和新数据
第4行输入要删除的位置
第5行输入要删除的位置
第6行输入要查找的位置
第7行输入要查找的位置

输出

n
数据之间用空格隔开,

第1行输出创建后的单链表的数据

每成功执行一次操作(插入或删除),输出执行后的单链表数据

每成功执行一次查找,输出查找到的数据

如果执行操作失败(包括插入、删除、查找等失败),输出字符串error,不必输出单链表

样例输入

6 11 22 33 44 55 66
3 777
1 888
1
11
0
5

样例输出

11 22 33 44 55 66
11 22 777 33 44 55 66
888 11 22 777 33 44 55 66
11 22 777 33 44 55 66
error
error
44

AC代码

#include<iostream>
using namespace std;

struct Node
{
	int data;
	Node* next;
	Node(int data = 0, Node* next = NULL) :data(data), next(next) {}
};


class LinkLisk {
	Node* head;
public:
	LinkLisk() {
		int n;
		cin >> n;
		head = new Node(n);
		Node* p = head;
		while (n--)
		{
			int data;
			cin >> data;
			p->next = new Node(data);
			p = p->next;
		}
	}

	void insert(int index, int data)
	{
		if (index < 1 || index > head->data + 1)
		{
			puts("error");
			return;
		}

		Node* p = head;
		for (int i = 1; i < index; i++)
			p = p->next;
		Node* s = new Node(data, p->next);
		p->next = s;

		head->data++;
		print();
	}

	void erase(int index) {
		if (index<1 || index>head->data)
		{
			puts("error");
			return;
		}

		Node* p = head;
		for (int i = 1; i < index; i++)
			p = p->next;
		Node* s = p->next;
		p->next = s->next;
		delete s;

		head->data--;
		print();
	}

	void find(int index) {
		if (index<1 || index>head->data)
		{
			puts("error");
			return;
		}

		Node* p = head;
		for (int i = 0; i < index; i++)
			p = p->next;
		cout << p->data << endl;

	}

	void print() {
		Node* p = head->next;
		for (int i = 0; i < head->data; i++)
		{
			cout << p->data << " ";
			p = p->next;
		}
		cout << endl;
	}
};
int main() {
	LinkLisk l;
	l.print();

	for (int i = 0; i < 2; i++) {
		int index, data;
		cin >> index >> data;
		l.insert(index, data);
	}

	for (int i = 0; i < 2; i++) {
		int index;
		cin >> index;
		l.erase(index);
	}

	for (int i = 0; i < 2; i++) {
		int index;
		cin >> index;
		l.find(index);
	}
	return 0;
}
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

曹无悔

请支持我的梦想!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值