散列表
来源:互联网 发布:淘宝收藏按钮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");}
- 散列表
- 散列表
- 散列表
- 散列表
- 散列表
- 散列表
- 散列表
- 散列表
- 散列表
- 散列表
- 散列表
- 散列表
- 散列表
- 散列表
- 散列表
- 散列表
- 散列表
- 散列表
- Sequential Task Process based on Spring Event Framework
- IIS7.5 配置 PHP 5.3.5
- Android传感器概述(一)
- poj 1390 Blocks(DP)
- Uncaught Error: Error calling method on NPObject.
- 散列表
- UVA 10759 Dice Throwing(dp 概率)
- 【Android】第三方QQ账号登录的实现
- 读取sav文件失败
- 查看oracle锁表相关脚本
- WebService:使用tcp/ip monitor拦截请求
- Android传感器概述(二)
- 2013.11.07
- Android Activity生命周期