散列表查找(哈希表)

一、概述:

散列技术:散列技术是一种通过哈希函数(散列函数)将关键字(Key)映射到存储位置的方法,目的是快速定位数据。其核心思想是将数据的存储位置与关键字建立直接关联,从而实现高效的查找、插入和删除操作。

散列表(哈希表):散列表是一种基于散列技术实现的数据结构,它通过哈希函数将关键字映射到数组的某个位置(槽,Slot),从而实现快速访问。

二、构造方法:

除留取余法:这是最常用的构造方法,对关键字取模,求出余数,让余数作为散列地址

公式:【f(key)=key%p(p<=散列表的长度)】

三、处理冲突的方法:

1、开放地址法:

当发生冲突时,通过某种规则寻找下一个空槽。常见的开放地址法有:

  • 线性探测(Linear Probing)

    • 公式f_i(key) = (f(key) + i) % m(i=1,2,3...)
    • 示例
      • 散列表长度 m=10,p=7,处理 29 和 15 的冲突:
        • 29 初始地址为 1(冲突),探测下一个位置:(1+1)%10=2(空槽,存入位置 2)。
    • 问题:容易形成 “聚集”(Cluster),导致后续冲突频繁。
  • 二次探测(Quadratic Probing)

    • 公式f_i(key) = (f(key) + i²) % m(i=1,2,3...)
    • 示例
      • 冲突时,依次探测位置f(key)+1², f(key)+2², f(key)+3²...
    • 优点:减少线性探测的聚集问题。
  • 伪随机探测

    • 公式f_i(key) = (f(key) + random(i)) % m(random (i) 为随机数序列)。

2、链地址法:将所有哈希地址相同的元素存储在同一个链表中。哈希表每个位置对应一个链表头节点,冲突的元素插入到对应链表中。

 

 四、参考代码:

#include<iostream>
#define NULLKEY -32768  // 定义空键标记,用于初始化哈希表,表示该位置未存储数据

using namespace std;

// 哈希函数:使用除留取余法将关键字映射到哈希表位置
// 此处固定使用11作为模数
int Hash(int key){
    int add;
    add=key%11;
    return add;
}

// 插入函数:将关键字插入哈希表
// 参数:h-哈希表指针,key-待插入的关键字
void InsertHash(int* h,int key){
    int add=Hash(key);  // 计算初始哈希位置

    // 线性探测处理冲突:如果当前位置已被占用,则尝试下一个位置
    while(h[add]!=NULLKEY){   
        add=(add+1)%11;     
    }
    h[add]=key;  // 找到空位置后插入关键字
}

// 查找函数:在哈希表中查找指定关键字
// 参数:h-哈希表指针,key-待查找的关键字
// 返回值:若找到返回关键字位置,未找到返回-1
int SearchHash(int* h,int key){
    int add=Hash(key);  // 计算初始哈希位置
    int start=add;      // 记录初始位置,用于判断是否遍历完整个哈希表

    // 线性探测查找:如果当前位置不是目标关键字,则继续查找下一个位置
    while(h[add]!=key){
        add=(add+1)%11; 
        // 如果回到初始位置,说明已遍历完整个哈希表,未找到目标关键字,返回-1 
        if(add==start)    
            return -1;
    }
    return add;  // 找到目标关键字,返回其位置
}

int main(){
    int t;
    cin>>t;  // 输入测试用例数量
    
    while(t--){
        int m,n,i;
        int *h;
        cin>>m>>n;    // m为哈希表大小,n为关键字数量
        
        // 创建哈希表并初始化为NULLKEY
        h=new int[m];
        for(i=0;i<m;i++){
            h[i]=NULLKEY;
        }
        
        // 输入n个关键字并插入哈希表
        for(i=0;i<n;i++){
            int key;
            cin>>key;
            InsertHash(h,key);
        }
        
        // 处理k次查询
        int k;
        cin>>k;       
        for(i=0;i<k;i++){
            int key;
            cin>>key;
            
            cout<<SearchHash(h,key)<<endl;  
        }
        
        delete[] h;   
    }
    
    return 0;
}

### 散列表哈希表的关系、区别与联系 散列表(Hash Table)和哈希表(Hash Map 或 Hash Set)是两种密切相关但又存在区别的数据结构。以下从定义、功能、实现方式等方面详细阐述它们的联系与区别。 #### 1. 定义与功能 散列表是一种通过哈希函数将键映射到存储位置的数据结构,其核心目标是实现高效的插入、删除和查找操作[^2]。散列表通常用于解决需要快速访问大量数据的应用场景。 哈希表可以看作是散列表的一种具体实现形式,它不仅包含散列表的基本功能,还可能扩展了额外的功能,例如支持键值对存储或动态调整大小等[^1]。因此,在许多情况下,哈希表散列表这两个术语可以互换使用。 #### 2. 冲突处理方式 散列表在设计时需要考虑冲突问题,即不同的键可能被映射到同一个存储位置。常见的冲突解决方法包括链地址法(拉链法)和开放定址法(如线性探测法、平方探测法等)。 - **链地址法**:每个存储位置维护一个链表,所有映射到同一位置的元素都存放在该链表中。这是散列表哈希表中常用的冲突解决方法之一[^4]。 - **开放定址法**:当发生冲突时,寻找下一个空闲位置进行存储。这种方法适用于某些特定场景,但在实际应用中不如链地址法普遍[^4]。 #### 3. 性能与效率 散列表的性能高度依赖于哈希函数的设计质量。一个好的哈希函数能够均匀分布键值,从而减少冲突的发生,提高查询效率[^3]。理论上,散列表的插入、删除和查找操作的时间复杂度为 O(1),但这需要满足低冲突率的前提条件[^2]。 哈希表作为散列表的一种实现形式,同样继承了这些特性,但在某些高级实现中,哈希表可能会引入额外的优化机制,例如动态扩容或再哈希技术,以进一步提升性能。 #### 4. 动态扩展能力 无论是散列表还是哈希表,都具备较好的动态扩展能力。当存储容量不足时,可以通过重新计算哈希值并分配更大的存储空间来完成扩展。这种特性使得两者在大规模数据存储和查询场景中表现出色。 #### 5. 联系总结 - 哈希表可以被视为散列表的一种具体实现形式,二者的核心思想一致,均依赖于哈希函数完成键值到存储位置的映射。 - 在实际应用中,哈希表通常指代支持键值对存储的数据结构,而散列表则更强调底层的存储机制和冲突解决策略。 ```python # 示例代码:简单的哈希表实现(基于字典) class SimpleHashTable: def __init__(self, size=10): self.size = size self.table = [[] for _ in range(size)] def hash_function(self, key): return hash(key) % self.size def insert(self, key, value): index = self.hash_function(key) bucket = self.table[index] for i, (k, v) in enumerate(bucket): if k == key: bucket[i] = (key, value) # 更新值 return bucket.append((key, value)) # 插入新值 def get(self, key): index = self.hash_function(key) bucket = self.table[index] for k, v in bucket: if k == key: return v return None # 如果未找到键,则返回 None ``` #### 6. 区别总结 | 特性 | 散列表 | 哈希表 | |------------------|--------------------------------|-------------------------------| | 数据存储形式 | 单纯的键值映射 | 键值对存储 | | 功能扩展 | 较少 | 可能包含更多高级功能 | | 应用场景 | 通用高效存储和查询 | 更广泛,如缓存、数据库索引等 | ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值