散列查找——平方探测法

一、哈希函数

数字关键词:h(Key)=Key mod TableSize

int Hash(const ElementType Key,int TableSize)
{        
    return Key%TableSize;
 }

二、开放地址法声明

//开放地址法的类型声明
#define MaxTableSize 10000//允许开辟的最大散列表的长度
typedef int ElementType;//关键词类型 
typedef int Index;//散列地址类型 
typedef Index Position;//数据所在位置类型

//散列单元状态类型:合法元素,空元素,已删除元素
typedef enum{
    Legitimate,Empty,Deleted
}EntryType;

typedef struct HashEntry Cell;//散列表单元类型 
struct HashEntry{
    ElementType Data;//存放元素
    EntryType Info;//单元状态 
};
 

typedef struct TblNode *HashTable;//散列表类型
struct TblNode{
    int TableSize;//表的最大长度
    Cell *Cells;//存放散列单元数据的数组 
}; 

三、开放地址法的初始化

int Prime(int N)
{
    //返回小于等于N的最大素数
    int i,p;
    if(N>=1&&N<=3)p=N;
    else p=(N%2)?N:N-1;//取奇数 
    while(p<=N&&p>4){
        for(i=(int)sqrt(p);i>2;i--)
            if(!(p%i))break;//p不是素数
        if(i==2)break;//p是素数
        else p-=2; 
    } 
    return p;
}


HashTable CreateTable(int TableSize)
{
    HashTable H;
    int i;
    H=(HashTable)malloc(sizeof(struct TblNode));
    //保证散列表的最大长度为素数 
    H->TableSize =Prime(TableSize);
    H->Cells =(Cell *)malloc(sizeof(Cell)*H->TableSize);
    for(i=0;i<H->TableSize ;i++)
        H->Cells[i].Info  =Empty;//都置为“空单元” 
    return H;
}

四、平方探测法的查找函数

过程:

1.首先调用Hash函数计算地址,确定关键词所在的散列表的地址

2.查找位置

Position Find(HashTable H,ElementType Key)
{
    Position CurrentPos,NewPos;
    int CNum=0;//记录冲突次数 
    NewPos= CurrentPos=Hash(Key,H->TableSize );
    //当该位置的单元非空,并且不是要找的元素时,发生冲突
    while(H->Cells[NewPos].Info!=Empty&&H->Cells[NewPos].Data !=Key){
        //统计一次冲突,并判断奇偶性
        CNum++;
        if(CNum%2){//奇数次冲突 
            //增量为+[(CNum+1)/2]^2;
            NewPos=CurrentPos+((CNum+1)/2)*((CNum+1)/2);
            if(NewPos>=H->TableSize )
                NewPos=NewPos%H->TableSize ;//调整溢出的地址为合法地址 
        } else{//偶数次冲突 
            //增量为-(CNum/2)^2
            NewPos=CurrentPos-(CNum/2)*(CNum/2);
            while(NewPos<0)
                NewPos+=H->TableSize ;//调整溢出的地址为合法地址 
        }
    } //结束while循环
    return NewPos; 
 } 

五、平方探测法的插入函数

bool Insert(HashTable H,ElementType Key)
{
    Position Pos=Find(H,Key);//先检查Key是否存在
    if(H->Cells[Pos].Info !=Legitimate){
        //如果这个单元没有被占用,那么久可以插入Key
        H->Cells[Pos].Data =Key;
        H->Cells[Pos].Info =Legitimate;
        return true; 
    } else{
        printf("键值已经存在\n");
        return false;
    }
    
}

六、完整代码

//哈希函数——位移映射
#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>
#include<math.h>

//开放地址法的类型声明
#define MaxTableSize 10000//允许开辟的最大散列表的长度
typedef int ElementType;//关键词类型 
typedef int Index;//散列地址类型 
typedef Index Position;//数据所在位置类型

//散列单元状态类型:合法元素,空元素,已删除元素
typedef enum{
    Legitimate,Empty,Deleted
}EntryType;

typedef struct HashEntry Cell;//散列表单元类型 
struct HashEntry{
    ElementType Data;//存放元素
    EntryType Info;//单元状态 
};
 

typedef struct TblNode *HashTable;//散列表类型
struct TblNode{
    int TableSize;//表的最大长度
    Cell *Cells;//存放散列单元数据的数组 
}; 

//哈希函数
//数字:h(Key)=Key mod TableSize 
int Hash(const ElementType Key,int TableSize)
{        
    return Key%TableSize;
 }
 
int Prime(int N)
{
    //返回小于等于N的最大素数
    int i,p;
    if(N>=1&&N<=3)p=N;
    else p=(N%2)?N:N-1;//取奇数 
    while(p<=N&&p>4){
        for(i=(int)sqrt(p);i>2;i--)
            if(!(p%i))break;//p不是素数
        if(i==2)break;//p是素数
        else p-=2; 
    } 
    return p;
}


HashTable CreateTable(int TableSize)
{
    HashTable H;
    int i;
    H=(HashTable)malloc(sizeof(struct TblNode));
    //保证散列表的最大长度为素数 
    H->TableSize =Prime(TableSize);
    H->Cells =(Cell *)malloc(sizeof(Cell)*H->TableSize);
    for(i=0;i<H->TableSize ;i++)
        H->Cells[i].Info  =Empty;//都置为“空单元” 
    return H;
}
/*----------创建结束-------------*/
 
/*-------------平方探测法---------------*/

/*-----------查找----------*/
/*
过程: 
1.首先调用Hash函数计算地址,确定关键词所在的散列表的地址 
2.查找位置 
*/
Position Find(HashTable H,ElementType Key)
{
    Position CurrentPos,NewPos;
    int CNum=0;//记录冲突次数 
    NewPos= CurrentPos=Hash(Key,H->TableSize );
    //当该位置的单元非空,并且不是要找的元素时,发生冲突
    while(H->Cells[NewPos].Info!=Empty&&H->Cells[NewPos].Data !=Key){
        //统计一次冲突,并判断奇偶性
        CNum++;
        if(CNum%2){//奇数次冲突 
            //增量为+[(CNum+1)/2]^2;
            NewPos=CurrentPos+((CNum+1)/2)*((CNum+1)/2);
            if(NewPos>=H->TableSize )
                NewPos=NewPos%H->TableSize ;//调整溢出的地址为合法地址 
        } else{//偶数次冲突 
            //增量为-(CNum/2)^2
            NewPos=CurrentPos-(CNum/2)*(CNum/2);
            while(NewPos<0)
                NewPos+=H->TableSize ;//调整溢出的地址为合法地址 
        }
    } //结束while循环
    return NewPos; 
 } 

/*-----------查找结束----------*/

/*-----------插入----------*/
bool Insert(HashTable H,ElementType Key)
{
    Position Pos=Find(H,Key);//先检查Key是否存在
    if(H->Cells[Pos].Info !=Legitimate){
        //如果这个单元没有被占用,那么久可以插入Key
        H->Cells[Pos].Data =Key;
        H->Cells[Pos].Info =Legitimate;
        return true; 
    } else{
        printf("键值已经存在\n");
        return false;
    }
    
}

/*-----------插入结束----------*/

int main()
{
    int TableSize,i;
    int N;
    ElementType Key;
    printf("请输入散列表长度:");
    scanf("%d",&TableSize); 
    //创建 
    HashTable H=CreateTable(TableSize);
    //插入
    printf("请输入关键词个数:");
    scanf("%d",&N); 
    printf("请输入%d个关键词:",N);
    for(i=0;i<N;i++){
        scanf("%d",&Key);
        Insert(H,Key); 
    }
    //查找 
    printf("请输入需要查找的关键词个数:"); 
    scanf("%d",&N); 
    printf("请输入%d需要查找的关键词:",N);
    for(i=0;i<N;i++){
        scanf("%d",&Key);
        Position p=Find(H,Key);
        printf("关键词%d在散列表中的位置为:%d\n",Key,p);
    }

    return 0;
}

七、运行

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值