哈希表是种数据结构,它可以提供快速的插入操作和查找操作。哈希表也有一些缺点它是基于数组的,数组创建
后难于扩展,某些哈希表被基本填满时,性能下降得非常严重。这个问题是哈希表不可避免的,即冲突现象:对不同
的关键字可能得到同一哈希地址。
第一次接触哈希表时,它的优点多得让人难以置信。不论哈希表中有多少数据,插入和删除(有时包括侧除)只需
要接近常量的时间即0(1)的时间级。实际上,这只需要几条机器指令。
对哈希表的使用者一一人来说,这是一瞬间的事。哈希表运算得非常快,在计算机程序中,如果需要在一秒种内查
找上千条记录通常使用哈希表(例如拼写检查器)哈希表的速度明显比
树
快,树的操作通常需要O(N)的时间级。哈希
表不仅速度快,编程实现也相对容易。
哈希表也有一些缺点它是基于数组的,数组创建后难于扩展某些哈希表被基本填满时,性能下降得非常严重,所以程序虽必须要清楚表中将要存储多少数据(或者准备好定期地把数据转移到更大的哈希表中,这是个费时的过程)。
而且,也没有一种简便的方法可以以任何一种顺序〔例如从小到大〕遍历表中
数据项
。如果需要这种能力,就只能选择其他数据结构。
然而如果不需要有序遍历数据,并且可以提前预测数据量的大小。那么哈希表在速度和易用性方面是
无与伦比
的。
说了这么多,都是概念,只有结合代码去理解,才能真正懂得哈希表是如何存储数据的:
#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
#define FALSE 0
#define TRUE 1
typedef struct _Node
{
int nData ;
struct _Node * next ;
}Node ;
typedef struct _Hash_Table
{
Node * value[10] ; //指针数组
}Hash_table;
//创建hash表
Hash_table *create_hash_table()
{
Hash_table * pHash = (Hash_table*)malloc(sizeof(Hash_table)) ;
memset(pHash,0,sizeof(Hash_table)) ;
return pHash ;
}
//在Hash表中寻找数据
Node* find_data(Hash_table* pHash ,int nData)
{
Node* pNode ;
if(NULL == pHash) //若哈希表为空
{
return NULL ;
}
if(NULL == (pNode = pHash->value[nData%10])) //若哈希表中数组没有该成员,进入if条件句
{
return NULL ;
}
while(pNode) //当该结构体指针不为空时
{
if(nData == pNode->nData )
{
return pNode ; //返回找到数据的结构体的指针
}
pNode = pNode->next ;
}
return NULL ;
}
//在Hash表中添加数据
bool insert_data(Hash_table * pHash ,int nData)
{
Node * pNode ;
if(NULL == pHash) //判断传入指针是否有效
{
return FALSE ;
}
if(NULL ==pHash->value[nData%10]) //判断指针数组中有没有该成员,若没有则进入if条件句中
{
pNode = (Node*)malloc(sizeof(Node)) ;
memset(pNode,0,sizeof(Node)) ; //清空pNode指向的结构体
pNode->nData = nData ;
pHash->value[nData%10] = pNode ;
return TRUE;
}
if(NULL != find_data(pHash,nData)) //查找到该数据
{
return FALSE ;
}
pNode = pHash->value[nData%10] ; //指向该元素所在的链表
while(NULL != pNode->next)
{
pNode = pNode->next ;
}
pNode->next = (Node*)malloc(sizeof(Node)) ;
memset(pNode->next,0,sizeof(Node)) ;
pNode->next->nData = nData ;
return TRUE ;
}
//在Hash表中删除数据
bool delete_data(Hash_table* pHash , int nData)
{
Node* pHead ;
Node* pNode ;
if(NULL == pHash || NULL == pHash->value[nData%10])
{
return FALSE ;
}
if(NULL == (pNode = find_data(pHash,nData))) //并未找到该数据
{
return FALSE ;
}
if(pNode == pHash->value[nData%10]) //若找到该数据结点并且是数组成员首个结构体
{
pHash->value[nData%10] = pNode->next ;
free(pNode) ;
return TRUE ;
}
pHead = pHash->value[nData%10] ;
while(pNode != pHead->next) // 遍历找出所要删除的数据位置
{
pHead = pHead->next ;
}
pHead->next = pNode->next ;
free(pNode) ;
return TRUE ;
}
//打印哈希表
void show_hash_table(Hash_table* pHash)
{
Node* pNode = NULL;
for(int i = 0; i<10; i++) // 从第一个哈希表元素开始打印,直到最后一个元素
{
printf("value[%d]:",i) ;
for(pNode=pHash->value[i] ; NULL != pNode; pNode=pNode->next) // 打印下标为i的哈希表元素及该位置所链接的节点
{
printf("%d ",pNode->nData) ;
}
printf("\n") ;
}
}
int main()
{
Hash_table* my_Hash_table ;
my_Hash_table = create_hash_table() ; //创建哈希表
char a[10] ={23,12,67,42,78,91,56,8,32,28};
//添加数据
bool blTemp ;
for(int i = 0;i<10;i++)
{
blTemp = insert_data(my_Hash_table,a[i]) ;
if(blTemp == FALSE)
{
printf("对不起 %d 添加失败\n",a[i]) ;
}
}
//查找数据
Node* pNode ;
pNode = find_data(my_Hash_table,81) ;
if(pNode == NULL)
{
printf("未找到该数据!\n");
}
else
{
printf("成功找到:%d\n",pNode->nData) ;
}
//删除数据
blTemp = delete_data(my_Hash_table,12);
if(blTemp == FALSE)
{
printf("对不起 删除失败!\n") ;
}
else
{
printf("成功删除!\n") ;
}
//打印哈希表
show_hash_table(my_Hash_table) ;
return 0 ;
}