散列(哈希表)
来源:互联网 发布:乌克兰危机 知乎 编辑:程序博客网 时间:2024/06/08 05:31
散列是一种用于以常数平均时间执行插入、删除和查找的技术。理想的散列表数据结构是一个包含有关键字的具有固定大小的数组。典型情况下,一个关键字就是一个带有相关值的字符串。
散列函数:如果输入的关键字是整数,则一般方法是直接返回“Key mod TableSize”的结果,除非Key具有某些不理想的性质。例如,若表的大小是10而关键字都以0为个位,则此时上述标准的散列函数就是一个不好的选择。为了避免上面那种情况,通常保证表的大小是素数。
冲突:如果当一个元素被插入时另一个元素已经存在(散列值相同),那么就产生一个冲突,这个冲突需要消除。解决冲突的方法有:分离连接法和开放定址法。
一、分离链接法
分离链接法是将散列到同一个值的所有元素保留到一个表中。
#include<iostream>
using namespace std;
typedef struct listNode {
const char *value;
struct listNode* next;
}ListNode;
typedef struct hashTable {
int tableSize;
ListNode **theLists;
}HashTable;
unsigned int Hush(const char* key,int tableSize);
HashTable* InitHashTable(int tableSize);
ListNode* Find(const char *key,HashTable *H);
void Insert(const char *key,HashTable *H);
unsigned int
Hush(const char *key,int tableSize)
{
unsigned int hashVal = 0;
while (*key != '\0')
hashVal = (hashVal << 5) + *key++;
return hashVal % tableSize;
}
HashTable*
InitHashTable(int tableSize)
{
int i;
HashTable *H;
H = (HashTable*)malloc(sizeof(struct hashTable));
if (H == NULL)
printf("out of space for H!");
H->theLists = (ListNode**)malloc(sizeof(struct listNode)*tableSize);
if (H->theLists == NULL)
printf("out of space for H->theLists");
for (i = 0; i < H->tableSize; i++) {
H->theLists[i] = (ListNode*)malloc(sizeof(struct listNode));
if (H->theLists[i] == NULL)
printf("out of space");
else
H->theLists[i]->next = NULL;
}
return H;
}
ListNode*
Find(const char *key, HashTable *H)
{
ListNode *p;
ListNode *L;
L = H->theLists[Hush(key,H->tableSize)];
p = L->next;
while (p != NULL && p->value != key)
p = p->next;
return p;
}
void
Insert(const char *key, HashTable *H)
{
ListNode* p, *temp;
ListNode *L;
p = Find(key,H);
if (p == NULL)
{
temp = (ListNode*)malloc(sizeof(ListNode));
if (temp == NULL)
printf("out of space");
else {
L=H->theLists[Hush(key,H->tableSize)];
temp->next = L->next;
temp->value = key;
L->next = temp;
}
}
}
二、开放定址--平方探测法
分离链接法的缺点是需要指针,由于需要给新单元分配地址需要时间,导致算法速度有些慢。开放定址散列法是一种不用链表解决冲突的方法。
#include<iostream>
using namespace std;#define MINSIZE 100
static int MinTableSize = MINSIZE;
enum EntryKind {Legitimate,Empty,Deleted};
struct HashEntry
{
char* value;
enum EntryKind info;
};
typedef struct HashTb
{
int TableSize;
struct HashEntry *theCells;
}HashTable;
int NextPrime(int TableSize);
void handlError(char *msg);
unsigned int Hash(char *key,int TableSize);
HashTable* InitializeTable(int TableSize);
unsigned int Find(char*,HashTable *H);
void Insert(char*,HashTable *H);
HashTable* Rehash(HashTable *H);
unsigned int
Hash(char *key, int TableSize)
{
unsigned int hashVal=0;
while (*key != '\0')
hashVal = (hashVal << 5) + *key++;
return hashVal % TableSize;
}
HashTable*
InitializeTable(int TableSize)
{
HashTable *H;
int i;
if (TableSize < MinTableSize)
{
handlError("Table size is too small");
}
H = (HashTable*)malloc(sizeof(HashTable));
if (H == NULL)
handlError("malloc for H is error");
H->TableSize = NextPrime(TableSize);
H->theCells = (struct HashEntry*)malloc(sizeof(struct HashEntry)*H->TableSize);
if (H->theCells == NULL)
handlError("malloc for H->theCells is error");
for (i = 0; i < H->TableSize; i++)
H->theCells[i].info = Empty;
return H;
}
unsigned int
Find(char* key, HashTable *H)
{
unsigned int Pos;
int collisionNum;
collisionNum = 0;
Pos = Hash(key,H->TableSize);
while (H->theCells[Pos].info != Empty && H->theCells[Pos].value != key)
{
Pos = Pos + 2 * ++collisionNum - 1;
if (Pos >= H->TableSize)
Pos -= H->TableSize;
}
return Pos;
}
void
Insert(char* key, HashTable *H)
{
unsigned int Pos;
Pos = Find(key,H);
if (H->theCells[Pos].info != Legitimate)
{
H->theCells[Pos].info = Legitimate;
H->theCells[Pos].value = key;
}
}
HashTable*
Rehash(HashTable *H) //再散列
{
int i, oldSize;
HashEntry *oldCells;
oldCells = H->theCells;
oldSize = H->TableSize;
H = InitializeTable(2*oldSize);
for (i = 0; i < oldSize; i++)
if (oldCells[i].info == Legitimate)
Insert(oldCells[i].value,H);
free(oldCells);
return H;
}
void
handlError(char *msg)
{
fputs(msg,stderr);
fputc('\n',stderr);
exit(1);
}
阅读全文
1 0
- HashTable 哈希表/散列
- 散列/哈希表
- 散列(哈希表)
- 散列查找 哈希表 Hash
- 数据结构---散列(哈希表)
- 散列
- 散列
- 散列
- 散列
- 散列
- 散列
- 散列
- 散列
- 散列
- 散列
- 散列
- 散列
- 散列
- MySQL数据库提权小结
- easyui下面layout插件的使用案例
- iOS Storyboard unwind segues使用
- EF三种编程方式详细图文教程(C#+EF)之Database First
- java基础学习(二)
- 散列(哈希表)
- C++ 中malloc函数详解(转载)
- cobbler sync cobblerd does not appear to be running/accessible: error(111, 'Connection refused')
- 解析HTTP协议六种请求方法
- 迭代的相关经验
- projecteuler.net 1--Multiples of 3 and 5
- easyui的accordion折叠面板案例
- 软件安装(预习)
- EF三种编程方式详细图文教程(C#+EF)之Model First