基于平方探测法的哈希表实现

/*
  哈希表
    基本操作 :
      - 创建空的哈希表
      - 查找 key 对应的 value
      - 插入键值对 (平方探测法)

*/
#include <stdio.h>
#include <stdlib.h>

// hashTable 地址空间存放的结构体
struct Cell;
// hashTable 结构体
typedef struct HashTable* pointerHashTable;



// 操作函数 -------------------------------

int nextPrimeNumber(int n);
pointerHashTable initializeTable(int tableSize);
int hashFunction(pointerHashTable hashTable, int key);
int findBySquare(pointerHashTable hashTable, int key);
int insertBySquare(pointerHashTable hashTable, int key);
void printHashTable(pointerHashTable hashTable);

// end -----------------------------------



// hashTable 地址空间的状态
typedef enum { Legitimate, Empty, Deleted } EntryType;
typedef struct Cell {
  int value;
  int key;
  EntryType info;
}Cell;
typedef struct HashTable {
  int tableSize;
  Cell* theCells;
} HashTable;

// 获取一个不小于 n 的最小素数
int nextPrimeNumber(int n) {
  // 素数不会被大于一的数整除
  // 首先排除偶数, 在奇数里面找

  int p = (n % 2) ? n : n + 1;

  int maxNum = 10000;
  while (p < 10000) {
    // 书上这里i 的取值范围是 sqrt(p)-2 ,真的精悍
    int i = p - 1;
    for (;i > 1;i--) {
      if (0 == p % i) {
        break;
      }
    }
    if (i == 1) {
      return p;
    }
    p += 2;
  }
  return -1;
}
// 初始化哈希表
// 这里表的大小有点不同, 视频里老师讲的是用传进来的大小, 但是课本里是用比 tableSize 大的最小素数
// 我用的是课本里的, 方便哈希函数的使用
pointerHashTable initializeTable(int tableSize) {
  int size = nextPrimeNumber(tableSize);
  printf("next prime number = %d\n", nextPrimeNumber(tableSize));

  pointerHashTable hashTable = (pointerHashTable)malloc(sizeof(HashTable));
  hashTable->theCells = (Cell*)malloc(size * sizeof(Cell));
  hashTable->tableSize = size;

  for (int i = 0;i < size;i++) {
    hashTable->theCells[i].info = Empty;
  }
  return hashTable;
}
// 哈希函数
// 使用除留余数法
int hashFunction(pointerHashTable hashTable, int key) {
  return key % hashTable->tableSize;
}
// 查找 key
// 使用平方探测法, 但是有个问题, 表如果满了怎么办, 不就无限循环了
int findBySquare(pointerHashTable hashTable, int key) {
  // 得到哈希函数结果
  int currentPosition = hashFunction(hashTable, key);
  int newPosition = currentPosition;
  // 标志位, 记录平方探测法当前 di 是否为正
  // 课本直接用一个变量 count 取代两个变量, 代码不易读
  int sign = 1;
  int di = 1;
  printf("------>>>> insert %d , current position = %d\n", key, currentPosition);
  while (hashTable->theCells[newPosition].info != Empty && hashTable->theCells[newPosition].key != key) {
    printf("hash table position %d conflict ", newPosition);
    newPosition = currentPosition + sign * (di * di);
    while (newPosition >= hashTable->tableSize) {
      newPosition = newPosition - hashTable->tableSize;
    }
    while (newPosition < 0) {
      newPosition = newPosition + hashTable->tableSize;
    }
    printf(", new pos = %d\n", newPosition);
    if (sign == -1) {
      di++;
      sign = 1;
    }     else {
      sign = -1;
    }

  }
  return newPosition;
}
// 插入 key
// 使用平方探测法
int insertBySquare(pointerHashTable hashTable, int key) {
  // 先看一下表里面有没有这个键值对
  int position = findBySquare(hashTable, key);

  // 有就返回 -1 表示错误
  if (hashTable->theCells[position].info == Legitimate) {
    return -1;
  }   else {
    // 没有就插入
    hashTable->theCells[position].key = key;
    hashTable->theCells[position].info = Legitimate;
    return 0;
  }

}


//输出键值对
void printHashTable(pointerHashTable hashTable) {
  for (int i = 0;i < hashTable->tableSize;i++) {
    if (hashTable->theCells[i].info == Legitimate) {
      printf("%d ", hashTable->theCells[i].key);
    }     else {
      printf("%d ", -1);
    }
  }
}
int main() {
  pointerHashTable hashTable = initializeTable(100);

  // 测试一下平方探测
  int x = 8;
  for (int i = 0;i < 98;i++) {
    x++;
    insertBySquare(hashTable, x * i);
  }
  printHashTable(hashTable);
  //
  return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值