数据结构之哈希链表Hashtable

散列(Hashing)在现实中经常遇到按照给定的值进行查询的实例。在软件开发过程记录存放的位置和用于表示他的数据项直接的对应关系。这种数据结构记录了数据和数据位置的信息,这就是Hashing。

我们哈希链表的数据结构图示是这样的

                                                      

如图所示这就是整个hashtable的图书,其中红色部分其实是一个数组,里面存放的是链表,大家可以通过蓝色知道里面存放的是链表,绿色部分就是链表的一个结点,有数据域和指针域组成,紫色部分就是我们的数据域,里面的数据包含两部分,一部分是关键码,另一部分就是存放关键码整体数据的位置指针(比如我们要存放身份证号,但身份证号特别长,我们可以用身份证后的后六位作为标识,那么身份证后六位就是关键码,那个位置指针就可以找到全部身份证号的信息)。

首先我们要定义存储数据的数据结构

#define M 13 //一般为质数,降低哈希冲突
typedef int keytype;//关键码类型
typedef struct{}Record;//结果集

typedef struct//数据,就是图中的紫色部分
{
	keytype key;//定义关键码
	Record *recptr;//记录指针
}ElemType;

然后就是定义结点

struct HashNode//哈希链表的结点,由元素+指针构成。相当于图中的绿色部分
{
	ElemType data;
	HashNode *next;
};

接下来就是哈希表,就是那个数组

typedef struct//哈希表,相当于图中红色部分
{
	HashNode*table[M];//数组
	int cursize;//当前元素个数
}HashTable;

我们把整体的数据结构定义好以后来说说这个哈希链表的思想。

首先我们要根据建立关键码和存储位置有关的对应函数关系,这个函数我们称为散列方法,使得每个关键码都能对应唯一一个存储位置。一般我们通过取余法来实现。这个也叫转换函数。通过这个函数可以直接找到哈希表的下标位置

int Hash(int val)//哈希函数返回哈希表的某个位置
{
	return val%M;//这里面的M我们定位13,一般是质数防止哈希冲突
}

找下标位置以后我们就要把数据存放到对应的数组下标,当table[0]种有数据我们就把下一个将要放入table[0]种的数据用链表的形式存放。

一下是链式哈希的全部实现代码

#include<iostream>
#include<assert.h>
using namespace std;
//链式哈希

#define M 13 //一般为质数,降低哈希冲突
typedef int keytype;//关键码类型
typedef struct{}Record;//结果集

typedef struct//元素
{
	keytype key;//定义关键码
	Record *recptr;//记录指针
}ElemType;

struct HashNode//哈希链表的结点,由元素+指针构成
{
	ElemType data;
	HashNode *next;
};

typedef struct//哈希表
{
	HashNode*table[M];//数组
	int cursize;//当前元素个数
}HashTable;

int Hash(int val)//哈希函数返回哈希表的某个位置
{
	return val%M;
}
void Init_HashTable(HashTable* pt)//初始化
{
	assert(pt!=NULL);
	for(int i=0;i<M;i++)
	{
		pt->table[i]=NULL;
	}
	pt->cursize=0;
}

HashNode* buynode()
{
	HashNode*s=(HashNode*)malloc(sizeof(HashNode));
	if(s==NULL) exit(EXIT_FAILURE);
	memset(s,0,sizeof(HashNode));
	return s;

}
HashNode* findNode(HashTable* pt,int kx)//查询
{
	assert(pt!=NULL);
	int pos=Hash(kx);
	HashNode*p=pt->table[pos];
	while(p!=NULL&&p->data.key!=kx)
	{
		p=p->next;
	}
	return p;
}
void freenode(HashNode*p)
{
	free(p);
}
bool Insert_HashTable(HashTable *pt,ElemType item)
{
	assert(pt!=NULL);
	HashNode*p=findNode(pt,item.key);
	if(p!=NULL)
	{
		return false;
	}
    p=buynode();//新建一个结点
	int pos=Hash(item.key);
	p->data=item;//
	p->next=pt->table[pos];
	pt->table[pos]=p;//头插法
	pt->cursize+=1;
	return true;
}
bool Delete_Hashnode(HashTable*pt,keytype item)
{
	assert(pt!=NULL);
	HashNode*p=findNode(pt,item);
	if(p==NULL)
	{
		return false;
	}
	int pos=Hash(item);
	p=pt->table[pos];
	HashNode*pr=p;
	if(p->data.key==item)
	{
		pt->table[pos]=p->next;
	}
	else
	{
	    while(p->next->data.key!=item)
	    {
	    	p=p->next;
	    	pr=pr->next;
	     }
		pr->next=p->next->next;
		p=NULL;
	}
	freenode(p);
	pt->cursize-=1;
	return true;
}
void show(HashTable*pt,int pos)
{
	HashNode *p=pt->table[pos];
	while(p!=NULL)
	{
		printf("%d ",p->data);
		p=p->next;
	}
	printf("\n");
}
int main()
{
	HashTable ht;
	Init_HashTable(&ht);

	ElemType item={-1,NULL};        //定义一个元素
	while (cin>>item.key,item.key!=-1)
	{
		Insert_HashTable(&ht,item);
	}
	show(&ht,1);

	Delete_Hashnode(&ht,14);

	show(&ht,1);
}

 

  • 10
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
哈希查找是一种通过哈希函数将关键字映射到哈希表中的位置,然后在该位置进行查找的方法。在C语言中,我们可以使用数组来实现哈希表。 首先,需要定义一个哈希表的结构体,包含两个成员:数组和数组长度。数组的每个元素是一个链表的头节点,用于解决哈希冲突。 ```c #define MAX_SIZE 100 // 链表节点 typedef struct ListNode { int key; int value; struct ListNode* next; } ListNode; // 哈希表 typedef struct HashTable { ListNode* array[MAX_SIZE]; int size; } HashTable; ``` 然后,需要实现以下几个操作: 1. 哈希函数:将关键字映射为哈希表的位置。 ```c int hashFunction(int key, int size) { return key % size; } ``` 2. 初始化哈希表。 ```c void initHashTable(HashTable* hashTable, int size) { hashTable->size = size; for (int i = 0; i < size; i++) { hashTable->array[i] = NULL; } } ``` 3. 插入元素。 ```c void insert(HashTable* hashTable, int key, int value) { int index = hashFunction(key, hashTable->size); ListNode* newNode = (ListNode*)malloc(sizeof(ListNode)); newNode->key = key; newNode->value = value; newNode->next = NULL; if (hashTable->array[index] == NULL) { hashTable->array[index] = newNode; } else { ListNode* cur = hashTable->array[index]; while (cur->next != NULL) { cur = cur->next; } cur->next = newNode; } } ``` 4. 查找元素。 ```c int search(HashTable* hashTable, int key) { int index = hashFunction(key, hashTable->size); ListNode* cur = hashTable->array[index]; while (cur != NULL) { if (cur->key == key) { return cur->value; } cur = cur->next; } return -1; // 没有找到 } ``` 这样,我们就可以使用哈希查找来快速检索数据了。注意,在实际应用中,还需要处理哈希冲突的情况,例如使用链地址法解决冲突。另外,还需要实现删除操作等其他功能。以上只是一个简单的哈希查找的示例。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值