//水平有限,酌情参考
#include<iostream>
using namespace std;
#define M 5 //哈希表长度
typedef struct linklist { //链表
int e; //值域
struct linklist* next; //指针域
}link;
//把哈希表和其容量标识设置为全局变量
link* Hash[M-1];
int space = 2*M;//链地址法,要求哈希表允许的关键字最大数目为2m
int FindLoc(int key) //求地址
{
return key % M;//取余
}
void InsertNode(int loc,int data) //向链表插入新结点
{
if(space==0){
cout << "----插入失败,哈希表容量已满" << endl;
return;
}
link* p = Hash[loc];
if (Hash[loc] == NULL) { //如果该地址还没有元素存储
Hash[loc] = new link;
Hash[loc]->e = data;
Hash[loc]->next = NULL;
space--; //容量减少
}
else{
while (p != NULL) { //此时该地址已有元素存储。先遍历链表查找是否有相同元素存在
if (p->e == data) {
cout << "----插入失败,该地址存在相同元素" << endl;
return;
}
p = p->next;
}//若没有相同元素存在,则用头插法插入新结点
link* ph = Hash[loc];
Hash[loc] = new link;
Hash[loc]->e = data;
Hash[loc]->next = ph;
space--;
}
cout << "----插入后,该地址储存的元素:" ;
p = Hash[loc];
while (p != NULL) {
cout << p->e<<" ";
p = p->next;
}
cout << endl;
}
void insert() {
cout << "Insert" << endl;
cout << "----请输入元素,输入-1停止输入" << endl;
int e, loc;
while (cin >> e && e != -1) {
loc = FindLoc(e);
InsertNode(loc, e); //把元素和得到的地址传入插入结点函数
}
}
void DelNode(int loc, int data) {
link* p1= Hash[loc];
link* p2 = p1; //主从指针
if (p1 == NULL) { cout << "----删除失败,该地址未存储元素"<<endl; return; }
while (p1!= NULL&&(p1->e!=data)) { //遍历寻找该元素
p2 = p1; //让p2指向p1的前驱结点
p1 = p1->next;
}
if(p1==NULL){ cout << "----删除失败,未找到该元素"<<endl; return; }
//此时p1已指向元素的结点,但先要判断该元素是否位于头结点
if (p1 == p2) //位于头结点
Hash[loc] = p1->next; //直接让头指针指向next
else //不位于头结点
p2->next = p1->next;
//free(p1);
space++;
cout << "----删除后,该地址储存的元素:";
p1 = Hash[loc];
while (p1 != NULL) {
cout << p1->e << " ";
p1 = p1->next;
}
cout << endl;
}
void del() {
cout << "Del" << endl;
cout << "----请输入元素,输入-1停止输入" << endl;
int e, loc;
while (cin >> e && e != -1) {
loc = FindLoc(e);
DelNode(loc, e);
}
}
void SearchNode(int loc, int data) {
link* p = Hash[loc];
if (p == NULL) {
cout << "----不存在该元素" << endl;
return;
}
while (p != NULL ) {
if (p->e == data) {
cout << "----查找成功,该元素处于地址" << loc << endl;
return;
}
p = p->next;
}
cout << "----不存在该元素" << endl;
return;
}
void search() {
cout << "Search" << endl;
cout << "请输入元素,输入-1停止输入" << endl;
int e, loc;
while (cin >> e && e != -1) {
loc = FindLoc(e);
SearchNode(loc, e);
}
}
void menu()
{
cout << "---------------------" << endl;
cout << " 1.插入关键字" << endl;
cout << " 2.删除关键字" << endl;
cout << " 3.查找关键字" << endl;
cout << " 4.结束程序" << endl;
cout << "---------------------" << endl;
int i;
while (cin>>i)
{
switch (i)
{
case 1:
insert();
menu();
break;
case 2:
del();
menu();
break;
case 3:
search();
menu();
break;
case 4:
exit(0);
menu();
break;
default:
cout << "错误的输入" << endl;
menu();
break;
}
}
}
int main()
{
memset(Hash, NULL, sizeof(Hash));//将头指针全初始化为NULL
menu();
}
编写控制台应用程序,提供以下菜单项:
1.插入关键字
2.删除关键字
3.查找关键字
4.结束程序
其中,“插入关键字”是指从键盘输入一个关键字,将关键字插入哈希表中,若插入的关键字已存储于哈希表中,则插入失败,显示提示信息;若插入关键字数目已超过哈希表设计容量,则插入失败,显示提示信息;其它情况则插入成功,显示提示信息。程序初始运行时,哈希表为空,通过插入多个关键字建立哈希表。
“删除关键字”是指从键盘输入一个关键字,若在哈希表中查找成功,则将关键字从哈希表中删除;若查找失败,显示提示信息。
“查找关键字”是指从键盘输入一个关键字,在哈希表中查找,显示查找成功与失败的提示信息。
已知哈希函数H(K)=K mod m,其中m为哈希表长度(程序中m应不小于10)。可选择用二次探测再散列或链地址法解决冲突。若选用二次探测再散列,装填因子设为0.8;若选用链地址法,要求哈希表允许的关键字最大数目为2m。