zoukankan      html  css  js  c++  java
  • 哈希表的运算算法

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

    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次
    ",k,i);
        }
        else
        {
            printf("失败:关键字%d,比较%d次
    ",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,到第一个关键字为空的地址9,需要比较5次,因此查找不成功的次数为5

    地址6,到第一个关键字为空的地址,9,需要比较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次
    ",k,i); 
        }
        else
        {
            printf("失败:关键字%d,比较%d次
    ",k,i);
        }
    }
    
  • 相关阅读:
    【leetcode】13. Roman to Integer
    【leetcode】12. Integer to Roman
    【leetcode】11. Container With Most Water
    Linux 学习总结(五)-linux 文件系统及相关命令
    Linux学习总结(四)-两种模式修复系统,单用户,救援模式
    Linux学习总结(三)之 putty,xshell远程连接及密钥认证篇
    Linux学习总结(二) 网络配置-NAT方式静态IP配置篇
    Linux学习总结(一) windos环境vmware安装centos7
    看完这篇Linux基本的操作就会了
    linux下tar命令详解
  • 原文地址:https://www.cnblogs.com/wangzheming35/p/13390463.html
Copyright © 2011-2022 走看看