1.为什么有哈希表?
因为哈希表的优点:常数时间的插入、查找、删除操作;调节内存和空间,结合了数组和链表的优点;以“键值对”存储数据;
//线性探测
#include
2 #include
3
4 #define SUCCESS (int)1
5 #define UNSUCCESS (int)0
6 #define HASHSIZE 12 /* 哈希表长度 */
7 #define NULLKEY -32768
8
9 typedef struct HashTable
10 {
11 int *elem; /* 哈希表元素存储地址,动态分配数组 */
12 int count; /* 当前数据元素的个数 */
13 }HashTable;
14
15 int m=0;
16
17 /* 初始化哈希表 */
18 int InitHashTable(HashTable *H)
19 {
20 int i;
21 m=HASHSIZE;
22 H->count=m;
23 H->elem=(int*)malloc(m*sizeof(int));
24 for(i=0;ielem[i]=NULLKEY;
26 }
27 return SUCCESS;
28 }
29
30 /* 哈希函数 */
31 int Hash(int key)
32 {
33 return key%m;
34 }
35
36 /* 将关键字插入散列函数 */
37 void InsertHash(HashTable *H,int key)
38 {
39 int addr=Hash(key); /* 求插入key的哈希地址 */
40 while(H->elem[addr]!=NULLKEY){
41 addr=(addr+1)%m; /* 如果不为空,发生冲突, 线性探测 */
42 }
43 H->elem[addr]=key; /* 直到有空位后插入关键字 */
44 }
45
46 /* 查找 */
47 int SearchHash(HashTable H,int key, int *addr)
48 {
49 *addr=Hash(key);
50 while(H.elem[*addr]!=key){ /* 如果H[*addr]不等于key, 则冲突,线性探测 */
51 *addr=(*addr+1)%m;
52 if(H.elem[*addr]=NULLKEY || *addr==Hash(key)){ /* 找不到或循环回到原点 */
53 return UNSUCCESS;
54 }
55 }
56 return SUCCESS;
57 }
//平方探测
#include
#include
#include
#include
#include
using namespace std;
#define MAX_TABLESIZE 10000 /* 允许开辟最大散列表长度 */
typedef int ElementType;
enum EntryType{Legitimate,Empty,Deleted}; /* 散列单元的状态类型 */
typedef struct HashEntry
{
ElementType data; //存放元素
enum EnTryType state; //单元状态
};
typedef struct HashEntry Cell;
typedef struct TblNode
{
int tablesize; //表的最大长度
Cell *cell; //存放散列单元数据的数据
}TblNode,*HashTable;
/* 返回大于n且不超过MAXTABLESIZE的最小素数 */
int NextPrime(int n)
{
int p=(n%2)?n+2:n+1; // 大于n的第一个奇数
int i;
while(p<=MAX_TABLESIZE){
for(i=(int)sqrt(p);i>2;i--){
if(p%i==0) break;
}
if(i==2){
break;
}else{
p+=2;
}
}
return p;
}
/* 创建哈希表 */
HashTable CreatTable(int table_size)
{
HashTable h=(HashTable)malloc(sizeof(TblNode));
h->tablesize=NextPrime(table_size);
h->cell=(Cell*)malloc(h->tablesize*sizeof(Cell));
for(int i=0;itablesize;i++){
h->cell[i].state=Empty;
}
return h;
}
/* 查找数据的初始位置,取余法确定散列函数 */
int Hash(ElementType key)
{
return key%11; //除留取余法
}
/* 如果key不在Hash表中,函数也会返回一个地址,这是不应该的;那该怎么处理呢?
* 不对不对,这个函数查找key是否已经在表中被占用,而是说key在Hash表中应该有
* 一席之地,即一定有位置可以存储key
* */
int Find(HashTable h,ElementType key)
{
int current_pos, new_pos;
int collision_num=0; //记录冲突次数
new_pos=current_pos=Hash(key);
while(h->cell[new_pos].state!=Empty&&h->cell[new_pos].data!=key){
collision_num++;
if(collision_num%2){ //处理奇数冲突
new_pos=current_pos+(collision_num+1)*(collision_num+1)/4;
if(new_pos>=h->tablesize){
new_pos=new_pos%h->tablesize;
}
}else{ //处理偶数冲突
new_pos=current_pos-(collision_num)*(collision_num)/4;
while(new_pos<0){
new_pos+=h->tablesize;
}
}
}
return new_pos;
}
bool Insert(HashTable h,ElementType key)
{
int pos=Find(h,key);
if(h->cell[pos].state!=Legitimate){
h->cell[pos].state=Legitimate;
h->cell[pos].data=key;
return true;
}else{
cout<<"key已经被占用"<tablesize;i++){
cout<cell[i].data<<" ";
}
cout<
//链地址
#include
#include
#include
#include
#include
using namespace std;
#define MAXTABLE_SIZE 10000 //允许最大的散列长度
#define KEYLENGTH 100 //允许关键字最大长度
typedef int ElementType;
struct LNode
{
ElementType data;
LNode *next;
};//链表节点
typedef struct LNode *PtrToNode;
typedef PtrToNode LinkList;
struct TblNode
{
int tablesize;
LinkList heads;
};//哈希表Key表
typedef struct TblNode *HashTable;
int NextPrime(int n)
{
int p=(n%2)?n+2:n+1;
int i;
while(p<=MAXTABLE_SIZE){
for(i=(int)sqrt(p);i>2;i--){
if(p%i==0){
break;
}
}
if(i==2){
break;
}else{
p+=2;
}
}
return p;
}
HashTable CreateTable(int table_size)
{
HashTable h=(HashTable)malloc(sizeof(TblNode));
h->tablesize=NextPrime(table_size);
h->heads=(LinkList)malloc(h->tablesize*sizeof(LNode));
for(int i=0;itablesize;i++){
h->heads[i].next=NULL;
}
return h;
}
int Hash(ElementType key, int n)
{
return key%11;
}
//找到pos=Hash(key), 在找到h->heads[pos]中找到key
LinkList Find(HashTable h,ElementType key)
{
int pos;
pos=Hash(key,h->tablesize);
LinkList p=h->heads[pos].next;
while(p&&key!=p->data){
p=p->next;
}
return p;
}
bool Insert(HashTable h,ElementType key)
{
LinkList p=Find(h,key);
if(!p){
LinkList new_link=(LinkList)malloc(sizeof(LNode));
new_link->data=key;
int pos=Hash(key,h->tablesize);
new_link->next=h->heads[pos].next;
h->heads[pos].next=new_link; //哑头链表,pos冲突的key值插入到链表头部
return true;
}else
{
cout<<"键值已经存在"<tablesize;i++){
p=h->heads[i].next;
while(p){
temp=p->next;
free(p);
p=temp;
}
}
free(h->heads);
free(h);
}
int main(int argc,char *argv[])
{
int a[]={47,7,29,29,11,16,92,22,8,3,50,37,89,94,21};
int n=15;
HashTable h=CreateTable(n);
for(int i=0;itablesize;i++){
LinkList p=h->heads[i].next;
while(p){
cout<data<<" ";
p=p->next;
}
cout<
参考链接:https://blog.csdn.net/weixin_38169413/article/details/81612307