哈希表的运算算法

一、开放定址法构造的哈希表的运算算法

1、哈希表类型

#define NULLKEY-1 //定义空关键字
#define DELKEY-2 //定义被删关键字
typedef int KeyType; //关键字类型
typedef struct
{
    KeyType key; //关键字域
    int count; //探测次数域
}HashTable;

2、插入建表算法

void InsertHT(HashTable ha[],int &n,int m,int p,KeyType k)
{
    int i,adr;
    adr=k%p; //计算哈希函数值
    if(ha[adr].key==NULLKEY||ha[adr].key==DELKEY)
    {
        ha[adr].key=k; //k可以直接放在哈希表中
        ha[adr].count=1;
    }
    else //发生冲突,用线性探测法解决冲突
    {
        i=1; //i记录k发生冲突的次数
        do
        {
            ard=(ard+1)%m; //线性探测
            i++;
        }while(ha[adr].key!=NULLKEY&&ha[adr].key!=DELKEY);
        ha[adr].key=k; //在adr处放置k
        ha[adr].count=i; //设置探测次数
    }
    n++; //哈希表中总元素个数增1
}

void CreateHT(HashTable ha[],int &n,int m,int p,KeyType keys[],int nl)
{
    for(int i=0;i<m;i++)
    {
        ha[i].key=NULLKEY;
        ha[i].count=0;
    }
    n=0; //哈希表中总元素个数从0开始递增
    for(i=0;i<nl;i++)
    {
        InsertHT(ha,n,m,p,keys[i]); //插入n个关键字
    }
}

3、删除算法

bool DeleteHT(HashTable ha[],int &n,int m,int p,KeyType k)
{
    int adr;
    adr=k%p; //计算哈希函数值
    while(ha[adr].key!=NULLKEY&&ha[adr].key!=k)
    {
        adr=(adr+1)%m; //线性探测
    }
    if(ha[adr].key==k) //查找成功
    {
        ha[adr].key=DELKEY; //删除k
        return true;
    }
    else
        return fales;
}

4、查找算法

void SearchHT(HashTable ha[],int m,int p,KeyType k)
{
    int i=1,adr;
    adr=k%p;
    while(ha[adr].key!=NULLKEY&&ha[adr].key!=k)
    {
        i++; //累计关键字比较次数
        adr=(adr+1)%m; //线性探测
    }
    if(ha[ard].key==k) //查找成功
    {
        printf("成功:关键字%d,比较%d次\n",k,i);
    }
    else
    {
        printf("失败:关键字%d,比较%d次\n",k,i);
    }
}

5、线性探测计算成功和不成功平均查找长度

对于查找不成功的理解:

根据哈希函数地址为mod7,因此任何一个数经散列函数计算以后的初始地址只可能在0~6的位置

查找0~6位置查找失败的查找次数为:

地址0,到第一个关键字为空的地址2需要比较3次,因此查找不成功的次数为3

地址1,到第一个关键字为空的地址2需要比较2次,因此查找不成功的次数为2

地址2,到第一个关键字为空的地址2需要比较1次,因此查找不成功的次数为1

地址3,到第一个关键字为空的地址4需要比较2次,因此查找不成功的次数为2

地址4,到第一个关键字为空的地址4需要比较1次,因此查找不成功的次数为1

地址5,到第一个关键字为空的地址2(比较到地址6,再循环回去)需要比较5次,因此查找不成功的次数为5

地址6,到第一个关键字为空的地址2(比较到地址6,再循环回去)需要比较4次,因此查找不成功的次数为4

二、拉链法构造的哈希表的运算

1、哈希表类型

typedef int KeyType; //关键字类型
typedef struct node
{
    KeyType key; //关键字域
    struct node *next; //下一个结点指针
}NodeType;
typedef struct
{
    NodeType *firstp; //首节点指针
}HashTable;

2、插入建表算法

void InsertHT(HashTable ha[],int &n,int p,KeyType k)
{
    int adr;
    adr=k%p; //计算哈希函数值
    NodeType *q;
    q=(NodeType *)malloc(sizeof(NodeType));
    q->key=k; //创建结点q,存放k
    q->next=NULL;
    if(ha[adr].firstp==NULL) //若单链表adr为空
    {
        ha[adr].firstp=q;
    }
    else
    {
        q->next=ha[adr].firstp; //头插法
        ha[adr].firstp=q;
    }
    n++; //哈希表中结点总个数增1
}

void CreateHT(HashTable ha[],int &n,int m,int p,KeyType keys[],int nl)
{
    for(int i=0;i<m;i++) //置初值
    {
        ha[i].firstp=NULL;
    }
    n=0;
    for(i=0;i<nl;i++)
    {
        InsertHT(ha,n,p,keys[i]); //插入n个关键字
    }
}

3、删除算法

bool DeleteHT(HashTable ha[],int &n,int m,int p,KeyType k)
{
    int adr;
    adr=k%p; //计算哈希函数值
    NodeType *q,*preq;
    q=ha[adr].firstp; //q指向首节点
    if(q==NULL)
        return false;
    if(q->key==k) //首节点为k
    {
        ha[adr].firstp=q->next; //删除结点q
        free(q);
        n--;
        return true;
    }
    preq=q; q=q->next; //首节点不为k
    while(q!=NULL)
    {
        if(q->key==k) //查找成功
            break; //退出循环
        q=q->next;
    }
    if(q!=NULL) //查找成功
    {
        preq->next=q->next; //删除结点q
        free(q);
        n--; //结点总数减1
        return true;
    }
    else
        return false;
}

4、查找算法

void SearchHT(HashTable ha[],int m,int p,KeyType k)
{
    int i=1,adr;
    adr=k%p;
    NodeType *q;
    q=ha[adr].firstp; //q指向对应单链表的首节点
    while(q!=NULL) //扫描adr单链表所有结点
    {
        i++;
        if(q->key==k) //查找成功
            break;
        q=q->next;
    }
    if(q!=NULL)
    {
       printf("成功:关键字%d,比较%d次\n",k,i); 
    }
    else
    {
        printf("失败:关键字%d,比较%d次\n",k,i);
    }
}

猜你喜欢

转载自www.cnblogs.com/wangzheming35/p/13390463.html