算法学习 - Hash Table操作,分离链接法解决哈希冲突

分离链接法

hash table是映射机制的,最大的优点就是它的操作是O(1)级别的。但是会出现哈希冲突,这就需要几种办法来解决。这里先说一种:分离链接法。

就是当插入的位置已经存在一个值之后,那么在这个值之后插入,就可以了,也叫拉链法。(但是其实会降低查找速度,变成O(n)级别)

下面是代码:

//
//  main.cpp
//  HashTable_SeparateChaining
//
//  Created by Alps on 14-8-5.
//  Copyright (c) 2014年 chen. All rights reserved.
//

#include <iostream>
#include <math.h>
#include "HashTable.h"
#define MinTableSize 1

using namespace std;

bool Prime(int size){
    for (int i = 2; i < sqrt(size); i++) {
        if (size%i == 0) {
            return false;
        }
    }
    return true;
}

int NextPrime(int Tablesize){
    if (Tablesize <= 2) {
        return 2;
    }else{
        while (!Prime(Tablesize)) {
            Tablesize++;
        }
        return Tablesize;
    }
    return Tablesize;
}

HashTable InitializeTable(int Tablesize){
    HashTable H;
    int i;

    if (Tablesize < MinTableSize) {
//        Error("table size is too small!");
        exit(0);
    }
    H = (HashTable)malloc(sizeof(struct HashTb));
    if (H == NULL) {
        //Error("out of space");
        exit(0);
    }
    H->Tablesize = NextPrime(Tablesize);
    H->TheList = (List*)malloc(sizeof(List) * H->Tablesize);
    for (i = 0; i < H->Tablesize; i++) {
        H->TheList[i] = (List)malloc(sizeof(struct ListNode));
        H->TheList[i]->Next = NULL;
    }

    return H;
}

int Hash(int key, int Tablesize){
    return key%Tablesize;
}

Position Find(ElementType key, HashTable H){
    int i = Hash(key, H->Tablesize);
    List L = H->TheList[i]->Next;
    while (L != NULL && L->element != key) {
        L = L->Next;
    }
    return L;
}

void Insert(ElementType key, HashTable H){
    if (Find(key, H) == NULL) {
        int i = Hash(key, H->Tablesize);
        List L = (List)malloc(sizeof(struct ListNode));
        L->element = key;
        Position P = H->TheList[i];
        L->Next = P->Next;
        P->Next = L;
    }
}

int main(int argc, const char * argv[])
{
    HashTable H = InitializeTable(10);
    printf("%d\n",H->Tablesize);
    Insert(5, H);
    Insert(3, H);
    Position P = Find(5, H);
    printf("%d\n",P->element);
    return 0;
}

下面是头文件:

//
//  HashTable.h
//  HashTable_SeparateChaining
//
//  Created by Alps on 14-8-5.
//  Copyright (c) 2014年 chen. All rights reserved.
//

#ifndef HashTable_SeparateChaining_HashTable_h
#define HashTable_SeparateChaining_HashTable_h
#define ElementType int

struct ListNode;
typedef struct ListNode *Position;
struct HashTb;
typedef HashTb *HashTable;

HashTable InitializeTable(int Tablesize);
void Destory(HashTable H);
Position Find(ElementType key, HashTable H);
void Insert(ElementType key, HashTable H);

#endif

struct ListNode{
    ElementType element;
    Position Next;
};

typedef Position List;

struct HashTb{
    int Tablesize;
    List * TheList;
};

算法学习 - Hash Table操作,分离链接法解决哈希冲突,布布扣,bubuko.com

时间: 2024-12-17 12:27:43

算法学习 - Hash Table操作,分离链接法解决哈希冲突的相关文章

算法学习 - HashTable开放地址法解决哈希冲突

开放地址法解决哈希冲突 线性开放地址法 线性开放地址法就是在hash之后,当发现在位置上已经存在了一个变量之后,放到它下一个位置,假如下一个位置也冲突,则继续向下,依次类推,直到找到没有变量的位置,放进去. 平方开放地址法 平方地址法就是在hash之后,当正确位置上存在冲突,不放到挨着的下一个位置,而是放到第2^0位置,假如继续冲突放到2^1的位置,依次2^3... 直到遇到不冲突的位置放进去. 双散列开放地址法 双散列同上,不过不是放到2^的位置,而是放到key - hash(key, tab

数据结构--散列(分离链接法解决冲突)

散列方法的主要思想是根据结点的关键码值来确定其存储地址:以关键码值K为自变量,通过一定的函数关系h(K)(称为散列函数),计算出对应的函数值来,把这个值解释为结点的存储地址,将结点存入到此存储单元中.检索时,用同样的方法计算地址,然后到相应的 单元里去取要找的结点.通过散列方法可以对结点进行快速检索.散列(hash,也称"哈希")是一种重要的存储方式,也是一种常见的检索方法. 因此,散列函数更像是一种映射,散列函数的选择有很多种,下面以散列函数为关键值对10取余为例,说明散列的插入关键

【干货】C++哈希桶(开链法解决哈希冲突)类的实现

开链法(哈希桶)是解决哈希冲突的常用手法,结构如下: 数据结构的设计思路是这样的,定义一个K-V的链式节点(Node),以数组方式存储节点指针 实现代码如下: #include<vector> #include"HashTable.h" size_t GetSize() { static size_t index = 0; const int _PrimeSize = 28; static const unsigned long _PrimeList[_PrimeSize]

散列之分离链接法

1 #include <vector> 2 #include <list> 3 #include <string> 4 #include <algorithm> 5 using std::vector; 6 using std::list; 7 using std::string; 8 using std::find; 9 10 int hash(const string &key) 11 { 12 int hashVal = 0; 13 14 fo

解决hash冲突之分离链接法

解决hash冲突之分离链接法 分离链接法:其做法就是将散列到同一个值的所有元素保存到一个表中. 这样讲可能比较抽象,下面看一个图就会很清楚,图如下 相应的实现可以用分离链接散列表来实现(其实就是一个linkedList数组) 至于基本的增加.删除和查询的思路都是先根据散列函数来确定遍历哪个链表.然后再到被确定的链表中执行一次查找,然后再进行相应的操作. 接下来就讲几个注意点吧 (一)什么时候需要rehash来扩大散列表的大小 讲这个的时候,先介绍一下什么是装填因子. 装填因子 = 关键字个数 /

习题5.11 分离链接法的删除操作函数 (20分)

试实现分离链接法的删除操作函数. 函数接口定义: bool Delete( HashTable H, ElementType Key ); 其中HashTable是分离链接散列表,定义如下: typedef struct LNode *PtrToLNode; struct LNode { ElementType Data; PtrToLNode Next; }; typedef PtrToLNode Position; typedef PtrToLNode List; typedef struc

[C++]实现散列表的分离链接法的数据结构

散列表,英文叫做Hash Table,因此也叫哈希表,是一种根据关键字值来确定主存中存储位置的数据结构.通过一个散列函数(关于键值的函数),来确定存储该关键字的位置. 主要的方法有: 1.分离链接法(拉链法) 分离链接法的散列函数为 position = key % n. 即关键字的存储位置为关键字的值对表项的数量取模.若表项大小为13,对于关键值为27的项,存储在1(27 % 13 = 1)的表项处.为了减少冲突,n往往取素数.对于同余的关键字,采用 队列(链表) 的方式连接在一起,新放入的元

散列表的C语言实现-分离链接法

一:散列表的定义: 散列表的实现常常叫做散列,散列是一种用于以常数平均时间执行插入,查找,删除的技术,但是,那些需要元素间任何排序信息的操作将不会得到支持,如findmin,findmax等等.散列表的优点很明显,它的查询时间为常数,速度非常快,缺点就是元素间没有排序,对于一些需要排序的场合不适用.理想的散列表数据结构就是一个包含有关键字的具有固定大小的数组,用一个散列函数来跟据关键字的值来将关键字插入到表中.这是散列的基本想法,剩下的问题是要选择一个好的散列函数,当俩个关键字散列到同一个值得时

分离链接法实现散列表

散列表是一种用于查找的数据结构.其基本思想来自于索引,也可以看成是数组的一种扩展.对于一些数据信息,比如说图片文件名,如果我们要查找某张图片,通常将图片名作为关键字进行搜索.这个时候是不可能把图片名直接当成数组下标的,因此可以将图片名关键字通过某个函数映射为某个地址,或地址偏移量.那么每次要查找图片的时候直接输入关键字就能直接计算得出存储地址.其定义 T=h(k) 其中k为关键字,h为映射函数,T为得到的散列表,得到的函数值为地址或地址偏移量. 如果不同关键字通过某函数得到的散列值(地址偏移量)