数据结构----哈希表以及哈希冲突

一.哈希表的建立

(1)哈希法又称散列法,通过哈希函数来快速存取元素,由此建立起来的存储表成为哈希表。

(2)哈希表/哈希函数的建立方法

<1>数字分析法:取元素各位数字上分布较为均匀的数字位组合为存取地址,各关键字中 d4和d7的取值分布较均匀,则哈希函数为:h(key)=h(d1d2d3…d7d8)=d4d7。例如,h(81346532)=43,h(81301367)=06。

<2>平方取中法:数字不处理时数字分布不均匀,平方后再数字分析。

<3>分段叠加法:将数字分割为位数相等的几部分,重叠或者移位相加,和舍去高位结果为地址值

<4>除留余数法:h(k) = k %p;

二.哈希冲突处理

哈希函数对于不同的元素可能计算出的地址是一样的,这就产生了哈希冲突,所以我们要处理哈希冲突。

1.开放定址法之 : 线性探测法

(1)思想:在冲突位置后面的不冲突位置插入,查找亦然。

(2)代码:

#include <iostream>
#include<bits/stdc++.h>
using namespace std;
typedef int ElemType;
typedef enum { Legitimate, Empty, Deleted } EntryType;
struct HashEntry{//节点
    ElemType Data;
    EntryType Info;
};
typedef HashEntry Cell;
struct TblNode{//哈希表
    int TableSize;//表长
    Cell *cells;//存储节点数组
};
typedef struct TblNode *HashTable;
int Hash(ElemType key,int sized){//哈希函数
     return key%sized;
}
int Find( HashTable H, ElemType key ){//查找函数(返回元素位置或者应该插入的位置)
    int pos = Hash(key,H->TableSize);
    for(int i = 0;i<H->TableSize;i++){
        int p = (pos + i)%H->TableSize;//!
        if(H->cells[p].Data==key||H->cells[p].Info==Empty)return p;
    }
    return -1;
}
void Insert(HashTable H,ElemType key){//插入函数
   int pos = Find(H,key);
   if(pos==-1){printf("Insert Error\n");return;}
   for(int i = 0;i<H->TableSize;i++){
        int p = (pos + i)%H->TableSize;
        if(H->cells[p].Info==Empty){
            H->cells[p].Data = key;
            H->cells[p].Info = Legitimate;
            return;
        }
   }
}
HashTable BuildTable(){//建立哈希表
    HashTable HB = (HashTable)malloc(sizeof(TblNode));
    scanf("%d",&HB->TableSize);
    HB->cells = (Cell*)malloc(sizeof(Cell)*HB->TableSize);
    for(int i = 0;i<HB->TableSize;i++)HB->cells[i].Info = Empty;//初始化
    for(int i = 0;i<HB->TableSize;i++){
        ElemType num;
        scanf("%d",&num);
        Insert(HB,num);//插入元素
    }
    return HB;
}
int main()
{
    HashTable H = BuildTable();
    for(int i = 0;i<H->TableSize;i++){
        if(i!=0)printf(" ");
        if(H->cells[i].Info==Empty||H->cells[i].Info==Deleted)printf("null");
        else printf("%d",H->cells[i].Data);
    }
    printf("\n");
    ElemType key;
    scanf("%d",&key);
    int pos = Find(H,key);
    if (pos==-1)
        printf("ERROR: %d is not found and the table is full.\n", key);
    else if (H->cells[pos].Info == Legitimate)
        printf("%d is at position %d.\n", key, pos);
    else
        printf("%d is not found.  Position %d is returned.\n", key, pos);

    return 0;
}

2.链地址法/分离链接法
(1)思想:把产生冲突的都放到一个集合里,查找时在集合中查找

(2)代码:

#include <iostream>
#include<bits/stdc++.h>
using namespace std;
typedef int ElemType;
struct LNode{//节点
   ElemType Data;
   LNode *next;
};
typedef LNode *List;
struct TblNode{//哈希表
    int TableSize;//表长
    List Heads;//各地址集合的头节点
};
typedef TblNode *HashTable;
int Hash(ElemType key,int Size){//哈希函数
    return key%Size;
}
HashTable InitTable(){//初始化表
    HashTable HB = (HashTable)malloc(sizeof(TblNode));
    scanf("%d",&HB->TableSize);
    HB->Heads = (List)malloc(sizeof(LNode)*HB->TableSize);
    for(int i = 0;i<HB->TableSize;i++){
        HB->Heads[i].next = NULL;
    }
    return HB;
}
List Find(HashTable H,int key){//查找函数(返回位置指针/空指针)
   int pos = Hash(key,H->TableSize);
   List p = H->Heads[pos].next;
   while(p!=NULL){
       if(p->Data==key)return p;
       p = p->next;
   }
   return p;
}
void Insert(HashTable H,ElemType key){//插入函数
   List p = Find(H,key);
   if(p==NULL){//没有该元素
      int pos = Hash(key,H->TableSize);
      List L = (List)malloc(sizeof(LNode));
      L->Data = key;//头插法
      L->next = H->Heads[pos].next;
      H->Heads[pos].next = L;
   }
   else{//已存在
       printf("Insert Error! Exit\n");
   }
}
void BuildTable(HashTable H){//建立哈希表
    for(int i = 0;i<H->TableSize;i++){
        ElemType num;
        scanf("%d",&num);
        Insert(H,num);
    }
}
bool Delete( HashTable H, ElemType key ){//删除元素
    List p = Find(H,key);
    if(p==NULL)return false;
    else{
        int pos = Hash(key,H->TableSize);
        List L = &H->Heads[pos];
        while(L->next->Data!=key){
            L = L->next;
        }
        LNode *q = L->next;
        L->next = q->next;
        q->next = NULL;
        free(q);
        printf("%d is deleted from list Heads[%d]\n",key,pos);
    }
    return true;
}
int main()
{
    HashTable H = InitTable();
    BuildTable(H);
    ElemType Key;
    int T;
    scanf("%d",&T);
    while(T--){
         scanf("%d",&Key);
         if (Delete(H, Key) == false)
            printf("ERROR: %d is not found\n", Key);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_40772692/article/details/84451417