散列表

来源:互联网 发布:淘宝收藏按钮ps文件 编辑:程序博客网 时间:2024/04/29 12:04

    散列表是一种以常数平均时间执行插入,删除,查找的数据结构。

    插入、删除、查找时都会对key进行hash计算,以确定需要操作的条目。

    我们在构造散列表时通常要考虑两个问题:1.如何将key均匀插入 2.如何解决key冲突。

一.散列函数

     散列函数主要用来解决均匀分布问题,该函数在操作散列表时执行频繁,所以我们需要的散列函数有以下需求:

         a.执行速度快

         b.在配合其他要素的情况下,使key能够均匀分布。


      一个好的散列函数如下:

         

typedef unsigned int Index;Index hashFunc(const char *key,int tableSize){  Index hashCode;  hashCode = 0;  while(*key != '\0'){    hashCode = (hashCode << 5) ^  *key++;  }  return hashCode % tableSize;}

以上散列函数并不是最好的,但是计算比较快速,tableSize在选择时最好是素数。


二.解决冲突

   无论散列函数如何优化,在散列key时肯定有几率时不同的key散列到相同的散列码从而使得同一个位置上需要插入多个值的情况。

  解决该问题的方法有多种,我们主要看分离链接法的实现。

  1.分离链接法

      基本思想:如果发生冲突,则使用一个链表存放这些冲突数据。

           头文件

         

#ifndef _HashMap_H#define _HashMap_H#define DefaultCapacity ( 17 )struct HashMapStruct;struct ListNodeStruct;struct EntryStruct;typedef unsigned int KeyType;typedef int ValueType;typedef struct ListNodeStruct *PtrToListNode;typedef struct HashMapStruct *PtrToHashMap;typedef struct EntryStruct *PtrToEntry;typedef PtrToListNode ListNode;typedef PtrToHashMap HashMap;typedef PtrToEntry Entry;HashMap initHashMap(int capacity);void put(HashMap map,char *key,ValueType value);static Entry find(HashMap map,KeyType hashKey);static Entry createEntry(KeyType hashKey);static KeyType hashFunc(const char *key,int capacity);void printHashMap(HashMap map);#endifstruct HashMapStruct{  int tableSize;  int capacity;  Entry *entryArray;  };struct ListNodeStruct{  ValueType value;  ListNode next;};struct EntryStruct{  KeyType key;  ListNode list;};

实现

#include <stdio.h>#include <stdlib.h>#include "hashmap.h"HashMap initHashMap(int capacity){  if(capacity > DefaultCapacity){     capacity = DefaultCapacity;  }  HashMap map;  map = malloc(sizeof(struct HashMapStruct));  map->tableSize =0;  map->capacity = capacity;  map->entryArray = malloc(sizeof(struct EntryStruct)*capacity);}void put(HashMap map,char *key,ValueType value){  if(map == NULL)     return;  Entry entry;  ListNode newNode,tempNode;  KeyType hashKey;  hashKey = hashFunc(key,map->capacity);  printf("key=%s,hashKey=%d\n",key,hashKey);  entry = find(map,hashKey);  if(entry == NULL){     if(map->tableSize == map->capacity){         printf("%s\n","map is full!");         return;     }      entry = createEntry(hashKey);  }  newNode = malloc(sizeof(struct ListNodeStruct));  newNode->value = value;  if(entry->list == NULL){      entry->list = newNode;      map->entryArray[map->tableSize] = entry;      map->tableSize++;  }else{    newNode->next = entry->list;    entry->list = newNode;    map->entryArray[map->tableSize] = entry;  }}static Entry find(HashMap map,KeyType key){   Entry entry,*entryArray;   entryArray = map->entryArray;   entry = NULL;   int i;   for(i = 0;i <= map->tableSize;i++){      if(entryArray[i] != NULL && entryArray[i]->key == key){         entry = entryArray[i];         break;      }   }   return entry;}static Entry createEntry(KeyType hashKey){  Entry entry;  entry = malloc(sizeof(struct EntryStruct));  entry->key = hashKey;  entry->list = NULL;  return entry;}static KeyType hashFunc(const char *key,int capacity){  KeyType hashCode;  hashCode = 0;  while(*key){     hashCode = ((hashCode << 5) + hashCode) ^ *key;     ++key;  }  return hashCode % capacity;}void printHashMap(HashMap map){  if(map == NULL)    return;  Entry *entryArray;  int index,tableSize;  tableSize = map->tableSize;  entryArray = map->entryArray;  printf("capacity=%d,tableSize=%d{",map->capacity,tableSize);  for(index=0;index<tableSize;index++){    printf("%d:%d;",entryArray[index]->key,entryArray[index]->list->value);  }  printf("\b}\n");}


原创粉丝点击