數據結構算法學習-哈希表-平方探測

哈希表定義及實現

哈希表也叫散列表,是快速執行查找,刪除,插入的技術,不支持元素排序信息。原理是通過把關鍵碼值映射到表中一個位置來訪問記錄,以加快查找的速度。
關鍵碼值到存儲位置的映射被稱爲哈希函數也叫散列函數,當不同關鍵key被映射到同一value時,稱爲衝突。
解決衝突主要有:
分離鏈接法:對Hash表中每個Hash值建立一個衝突表,即將衝突的幾個記錄以表的形式存儲在其中。
開發定址法:根據衝突算法找到空的單元爲止(線性探測法,平方探測法...)。

編程實例

算法實現

採用平方探測法的實現放在[email protected]:c-program/projecteuler.git上projecteulerccommonstruct目錄下elr_hash_int.h elr_hash_int.c兩個單元內。

解決問題

https://www.hackerrank.com/ch...
要求用一個map結構存放名字name和電話phone。

定義結構

#define MaxStr 20

typedef unsigned long int Index;
typedef Index Position;
typedef char *KeyType;
typedef long int *ValueType;

struct HashTbl;
typedef struct HashTbl *HashTable;

enum KindOfEntry { Legitimate, Empty, Deleted };

struct HashEntry {
  KeyType Key;
  ValueType Value;
  enum KindOfEntry Info;
};

typedef struct HashEntry Cell;

struct HashTbl {
  long int TableSize;
  Cell *TheCells;
};

初始化及釋放

HashTable InitializeTable(long int TableSize) {
  HashTable H;
  long int i;

  H = malloc(sizeof(struct HashTbl));
  if (H == NULL) {
    printf("Out of space!\n");
  }

  H->TableSize = TableSize;

  H->TheCells = malloc(sizeof(Cell) * H->TableSize);
  if (H->TheCells == NULL) {
    printf("Out of space!\n");
  }

  for (i = 0; i < H->TableSize; i++) {
    H->TheCells[i].Info = Empty;
    H->TheCells[i].Key = NULL;
    H->TheCells[i].Value = 0;
  }

  return H;
}

void DestroyTable(HashTable H) {
  int i;

  if (H == NULL) {
    return;
  }

  for (i = 0; i < H->TableSize; i++) {
    H->TheCells[i].Info = Empty;
    if (H->TheCells[i].Key != NULL) {
      free(H->TheCells[i].Key);
    }
  }

  free(H);
}

哈希及衝突插入操作

Position Hash(KeyType Key, long int TableSize) {
  long int keyValue = 0;
  register unsigned char *p;

  for (p = (unsigned char *)Key; *p; p++) {
    keyValue = 31 * keyValue + *p;
  }

  return keyValue % TableSize;
}

int KeyEqual(KeyType a, KeyType b) {
  if ((a == NULL) || (b == NULL)) {
    return 1;
  }

  return strcmp(a, b) == 0 ? 0 : 1;
}

int Find(KeyType Key, HashTable H, Position *Pos) {
  Position CurrentPos;
  long int CollisionNum;
  int rst = 0;

  CollisionNum = 0;
  CurrentPos = Hash(Key, H->TableSize);
  while (1) {
    if (H->TheCells[CurrentPos].Info == Empty)
      break;
    if (KeyEqual(H->TheCells[CurrentPos].Key, Key) == 0) {
      rst = 1;
      break;
    }
    CurrentPos += (++CollisionNum << 1) - 1;
    if (CurrentPos >= H->TableSize) {
      CurrentPos -= H->TableSize;
    }
  }

  *Pos = CurrentPos;
  return rst;
}

void Insert(KeyType Key, ValueType Value, HashTable H) {
  Position Pos;
  int exist;

  exist = Find(Key, H, &Pos);

  H->TheCells[Pos].Info = Legitimate;
  if (!exist) {
    H->TheCells[Pos].Key = malloc(sizeof(char) * MaxStr);
  }
  strcpy(H->TheCells[Pos].Key, Key);
  H->TheCells[Pos].Value = Value;
}

調用解決問題

#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main() {
  long int n = 0;
  scanf("%ld", &n);

  HashTable H = InitializeTable(n * 2);

  for (int i = 0; i < n; i++) {
    char name[20];
    long int phone;
    scanf("%s %ld", name, &phone);
    Insert(name, phone, H);
    }

    for (int i = 0; i < n; i++) {
      char name[20];
      Position Pos;
      int exist;
      scanf("%s", name);
      // while (() != '\n');
      exist = Find(name, H, &Pos);
      if (exist == 1) {
          ValueType Value = H->TheCells[Pos].Value;
          printf("%s=%ld\n", name, Value);
      } else {
        printf("Not found\n");
      }
      if (getchar() == EOF)
        break;
    }

    DestroyTable(H);
    
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章