查找 || 哈希表的c++实现

29 篇文章 5 订阅
27 篇文章 1 订阅

哈希表的构造方法:

  1. 直接定址法
  2. 数字分析法
  3. 平方取中法
  4. 折叠法
  5. 除留余数法
  6. 随机数法

处理冲突的方法:

  1. 开放地址法
    • 线性探测再散列
    • 二次探测再散列
    • 伪随机探测再散列
  2. 再哈希法
  3. 链地址法
  4. 建立一个公共溢出区

装填因子:

平均查找长度ASL跟哈希表构造方法和处理冲突的方法都有关。一般情况下,处理冲突方法相同的哈希表,其平均查找长度依赖于哈希表的装填因子:

α = 表 中 填 入 的 记 录 数 哈 希 表 的 长 度 \alpha = \frac{表中填入的记录数}{哈希表的长度} α=
α标志哈希表的装满程度,越小发生冲突的可能性就越小。

可证明得出:

线性探测再散列的哈希表ASL:
S n l ≈ 1 2 ( 1 + 1 1 − α ) S_{nl} \approx \frac{1}{2} (1+\frac{1}{1-\alpha}) Snl21(1+1α1)
随机探测再散列、二次探测再散列、再哈希的哈希表ASL:
S n r ≈ − 1 α ln ⁡ ( 1 − α ) S_{nr} \approx - \frac{1}{\alpha}\ln(1-\alpha) Snrα1ln(1α)
链地址法的ASL:
S n c ≈ 1 + α 2 S_{nc} \approx 1 + \frac{\alpha}{2} Snc1+2α

c++实现:
  • 包含创建,插入,删除,查找,打印,扩充哈希表等操作。
hpp:
//
//  HashTable.hpp
//  HashTable
//
//  Created by peiyu wang on 2019/3/28.
//  Copyright © 2019 peiyu wang. All rights reserved.
//

#ifndef HashTable_hpp
#define HashTable_hpp

#include <iostream>
#include <stdio.h>
using namespace std;

/* 全局变量 */
// 哈希表容量递增表,一个合适的素数序列
const int hashsize[] = {7, 13, 17, 101, 211, 307, 401, 503, 601, 701, 809, 907, 997};

/* 宏定义 */
#define DUPLICATE -1  // 表中已存在关键字
#define NULLKEY -2    // 标记此处无关键字
#define FULL -3       // 表已满(冲突次数达上限就认为表满)
#define EVER -4       // 此位置上曾删除过元素

/*类型定义*/
typedef int KeyType;
struct HashTable
{
    KeyType *elem; //数据元素存储基址
    int count;     //当前表中画关键字个数
    int sizeindex; //当前容量
};

/* 函数列表 */
// 初始化一个空的哈希表
void InitHash(HashTable &H);
// 创建哈希表
int CreateHash(HashTable &H);
// 哈希表关键字搜索,p指向查找成功后的元素位置
int SearchHash(HashTable H, KeyType key, int *p);
// 哈希表关键字插入
int InsertHash(HashTable &H, KeyType key);
// 哈希表删除操作
int DeleHash(HashTable &H, KeyType key);
// 重建哈希表
int RecreateHashTable(HashTable &H);
// 哈希函数
int fHash(HashTable H, KeyType key);
// 开放地址法寻找下一个探查位置
void collision(HashTable H, int *p);
// 输出哈希表中的关键字
void PrintHash(HashTable H);

#endif

cpp:
//
//  HashTable.cpp
//  HashTable
//
//  Created by peiyu wang on 2019/3/28.
//  Copyright © 2019 peiyu wang. All rights reserved.
//

#include "HashTable.hpp"
#include <queue>

void InitHash(HashTable &H)
{
    H.count = 0;
    H.sizeindex = 0;
    int newN = hashsize[H.sizeindex];
    H.elem = new KeyType [newN];
    for (int i = 0; i < newN; i++)
    {
        H.elem[i] = NULLKEY;
    }
}

int CreateHash(HashTable &H)
{
    InitHash(H);
    int n = 0;
    cout << "请输入哈希表元素个数: " << endl;
    cin >> n;
    while (n--)
    {
        KeyType k;
        cin >> k;
        InsertHash(H, k);
    }
    return 1;
}

int SearchHash(HashTable H, KeyType key, int *p)
{
    int c = 0; // 记录冲突的次数
    int sup = hashsize[H.sizeindex] / 2;
    *p = fHash(H, key);
    while (1)
    {
        if (H.elem[*p] == NULLKEY || H.elem[*p] == EVER)
            return NULLKEY;
        else if (H.elem[*p] == key)
            return DUPLICATE;
        else if (++c == sup)
            return FULL;
        else
            collision(H, p); //重新定位p的位置
    }
}
// 哈希表关键字插入
int InsertHash(HashTable &H, KeyType key)
{
    int p;
    int flag = SearchHash(H, key, &p);
    if (flag == FULL)
    {
        queue<KeyType> tmp;
        for (int i = 0; i < hashsize[H.sizeindex]; i++)
        {
            if (H.elem[i] != NULLKEY)
            {
                tmp.push(H.elem[i]);
            }
        }
        if (RecreateHashTable(H))
        {
            while (!tmp.empty())
            {
                InsertHash(H, tmp.front());
                tmp.pop();
            }
            InsertHash(H, key);
        }
        
    }
    if (flag == NULLKEY || flag == EVER)
    {
        H.elem[p] = key;
        H.count ++;
    }
    if (flag == DUPLICATE)
        return 0;
    return 1;
}
// 重建哈希表
int RecreateHashTable(HashTable &H)
{
    H.count = 0;
    H.sizeindex += 1;
    int newN = hashsize[H.sizeindex];
    if (H.elem)
    {
        delete H.elem;
    }
    H.elem = new KeyType [newN];
    if (!H.elem)
    {
        return 0;
    }
    for (int i = 0; i < newN; i++)
    {
        H.elem[i] = NULLKEY;
    }
    return 1;
}

int DeleHash(HashTable &H, KeyType key)
{
    int p = 0;
    int flag = SearchHash(H, key, &p);
    if (flag == DUPLICATE)
    {
        H.elem[p] = EVER;
        H.count--;
        return 1;
    }
    else
    {
        return 0;
    }
}

// 哈希函数
int fHash(HashTable H, KeyType key)
{
    
    return ((key * 2654435769) >> 28) % hashsize[H.sizeindex];
}
// 开放地址法寻找下一个探查位置
void collision(HashTable H, int *p)
{
    //简单的移位
    *p = (*p + 1) % hashsize[H.sizeindex];
}
// 输出哈希表中的关键字
void PrintHash(HashTable H)
{
    int i, v;
    
    v = hashsize[H.sizeindex];
    
    printf("哈希表容量为:%d,现有元素:%d 个,表中元素为:\n", v, H.count);
    
    for(i=0; i<v; i++)
    {
        if(H.elem[i]!=NULLKEY && H.elem[i]!=EVER)
            cout << H.elem[i] << " ";
    }
    
    printf("\n");
}

main:
//
//  main.cpp
//  HashTable
//
//  Created by peiyu wang on 2019/3/28.
//  Copyright © 2019 peiyu wang. All rights reserved.
//

#include "HashTable.hpp"

int main() {
    HashTable H;
    CreateHash(H);
    int p = 0;
    int r;
    r = SearchHash(H, 20, &p);
    if (r == DUPLICATE)
        cout << "查找成功" << endl;
    else
        cout << "查找失败" << endl;
    DeleHash(H, 20);
    PrintHash(H);
    r = SearchHash(H, 20, &p);
    if (r == DUPLICATE)
        cout << "查找成功" << endl;
    else
        cout << "查找失败" << endl;
    InsertHash(H, 20);
    r = SearchHash(H, 20, &p);
    if (r == DUPLICATE)
        cout << "查找成功" << endl;
    else
        cout << "查找失败" << endl;
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值