哈希表(散列)HashTable实现

  最近刷Leetcode发现凡是找字符串中重复字符或者数组中找重复数据的时候就不知道从何下手了。

  所以决定学习一下哈希表解题,哈希表的原理主要是解决分类问题,hash表是介于链表和二叉树之间的一种中间结构。链表使用十分方便,但是数据查找十分麻烦;二叉树中的数据严格有序,但是这是以多一个指针作为代价的结果。hash表既满足了数据的查找方便,同时不占用太多的内容空间,使用也十分方便。

  定义hash数据结构,我采用的解决冲突的方法是分离链接法。

  

//单链表结构
typedef struct listnode* position;
typedef struct listnode* list;
struct listnode{
    ElementType data;
    position next;
};
//hash表结构
typedef struct hashtbl*  hashtable;
struct hashtbl {
    int tablesize;
    list *thelists;
};

哈希散列函数index = key%tablesize

index HashFunc(const ElementType key,int tablesize)
{
    //unsigned int hashval = 0;
    //while(*key != ‘\0‘)
        //hashval = (hashval << 5) + *key++;
    //return hashval % tablesize;
    return key % tablesize;
}

创建hash表,并初始化

hashtable InitializeHashTable(int tablesize)
{
    hashtable H;
    H = (hashtable)malloc(sizeof(hashtable));
    if(NULL == H) return NULL;

    H->tablesize = tablesize;

    H->thelists = (list*)malloc(sizeof(list) * H->tablesize);
    int i = 0;
    for(i=0;i<H->tablesize;i++)//链表是有表头的单链表
    {
        H->thelists[i] = (list)malloc(sizeof(struct listnode));
        H->thelists[i]->next = NULL;
    }
    return H;
}

删除hash表

void DeleteHashTable(hashtable H)
{
    position P,tem;
    int i = 0;
    for(i=0;i<H->tablesize;i++)
    {
        P = H->thelists[i]->next;
        while(P != NULL)
        {
            tem = P;
            free(tem);
            P=P->next;
        }
    }
    free(H->thelists);
    free(H);
}

往hash表中插入新元素

position Find(ElementType key,hashtable H)
{
    position P;
    list L;
    L = H->thelists[ HashFunc( key, H->tablesize) ];
    P = L->next;
    while(P != NULL && P->data != key)
        P = P->next;

    return P;
}

void Insert(ElementType key,hashtable H)
{
    position pos,newnode;
    list L;
    pos = Find(key,H);
    if(pos == NULL)
    {
        newnode = (position)malloc(sizeof(position));
        L = H->thelists[ HashFunc( key, H->tablesize) ];
        newnode->data = key;
        newnode->next = L->next;
        L->next = newnode;
    }
}

打印hash表中所有的元素

void PrintHashTable(hashtable H)
{
    position P;
    int i = 0;
    for(i=0;i<H->tablesize;i++)
    {
        P = H->thelists[i]->next;
        printf("H->thelists[%d] = ",i);
        while(P != NULL)
        {
            printf("  %d",P->data);
            P=P->next;
        }
        printf("\n");
    }
}

测试main函数

int main()
{
    int num[10] = {3,45,5,64,7,9,8,3,75,75};
    hashtable H;
    H = InitializeHashTable(10);
    int i = 0;
    for(i=0;i<10;i++)
    {
        Insert(num[i],H);
    }
    PrintHashTable(H);
    DeleteHashTable(H);
}

头文件

#include <stdlib.h>
#include <stdio.h>
#include <stdbool.h>

typedef int ElementType;
typedef unsigned int index;

测试结果,可以看到图片中散列后在hash表中一样位置的都保存下来了,形成一个链表如数据75 5 45;但是相同的数据只保存一份,比如3和3,75和75

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-12-24 15:24:38

哈希表(散列)HashTable实现的相关文章

哈希表/散列表

哈希表/散列表,是根据关键字(key)直接访问在内存存储位置的数据结构. 构造哈希表的常用方法: 直接地址法---取关键字的某个线性函数为散列地址,Hash(Key) = Key或Hash(key) = A*Key + B, A,B为常数. 除留余数法---取关键值被某个不大于散列表长m的数p除后的所得的余数为散列地址. Hash(key) = key % p. 若采用直接地址法(Hash(Key) = Key)存在一定的缺陷. 当Key值特别大时,而Key之前的数很少,就会造成空间浪费.大多时

数据库表散列

http://dapple.iteye.com/blog/740338 数据库表散列: 思路:1.缩短查询耗时: 2.分拆表或者库,表小,查询自然快: 3.需要快速定位,hash算法可以做到这种(唯一)映射

(转)数据库表分割技术浅析(水平分割/垂直分割/库表散列)

数据库表分割技术包含以下内容:水平分割/垂直分割/库表散列.接下来将对以上分割进行详细介绍,感兴趣的朋友可以了解下,对你日后维护数据库是很有帮助的 一.水平分割 什么是水平分割?打个比较形象的比喻,在食堂吃饭的时候,只有一个窗口,排队打饭的队伍太长了,都排成S型了,这时容易让排队的人产生焦虑情绪,容易产生混乱,这时一个管理者站出来,增加多个打饭窗口,把那条长长的队伍拦腰截断成几队.更形象一点的理解,你拿一把“手术刀”,把一个大表猛的切了几刀,结果这个大表,变成了几个小表. 水平分割根据某些条件将

(转载)数据库表分割技术浅析(水平分割/垂直分割/库表散列)

一.数据库表分割技术 数据库表分割技术包含以下内容: 水平分割 垂直分割 库表散列 1.1.水平分割 什么是水平分割?打个比较形象的比喻,在食堂吃饭的时候,只有一个窗口,排队打饭的队伍太长了,都排成S型了,这时容易让排队的人产生焦虑情绪,容易产生混 乱,这时一个管理者站出来,增加多个打饭窗口,把那条长长的队伍拦腰截断成几队.更形象一点的理解,你拿一把“手术刀”,把一个大表猛的切了几刀,结果这个大表,变成了几个小表. 水平分割根据某些条件将数据放到两个或多个独立的表中.即按记录进分分割,不同的记录

HashTable-哈希表/散列表

HashTable-散列表/哈希表,是根据关键字(key)而直接访问在内存存储位置的数据结构.它通过一个关键值的函数将所需的数据映射到表中的位置来访问数据,这个映射函数叫做散列函数,存放记录的数组叫做散列表. 构造哈希表的几种方法 直接定址法--取关键字的某个线性函数为散列地址,Hash(Key)= Key 或 Hash(Key)= A*Key + B,A.B为常数. 除留余数法--取关键值被某个不大于散列表长m的数p除后的所得的余数为散列地址.Hash(Key)= Key % P. 平方取中法

[转]net中哈希表的使用 Hashtable

本文转自:http://www.cnblogs.com/gsk99/archive/2011/08/28/2155988.html 以下是PetShop中DBHelper中的使用过程: //创建哈希表 Hashtable to store cached parametersprivate static Hashtable parmCache = Hashtable.Synchronized(new Hashtable()); ... //缓存数据string cacheKey = "xxxx&q

2020年2月24日09:06:11,Hash散列

问题描述 /** 有一个公司,当有新的员工来报道时,要求将该员工的信息加入(id,性别,年龄,住址..),当输入该员工的id时,* 要求查找到该员工的所有信息.* ?要求: 1)不使用数据库,,速度越快越好=>哈希表(散列)* 2)添加时,保证按照id从低到高插入[课后思考:如果id不是从低到高插入,但要求各条链表仍是从低到高,怎么解决?]* 3)使用链表来实现哈希表, 该链表不带表头** */ 代码实现 package day0223 /* * 有一个公司,当有新的员工来报道时,要求将该员工的

9. 蛤蟆的数据结构进阶九哈希表实现

9. 蛤蟆的数据结构进阶九哈希表实现 本篇名言:"人们所努力追求的庸俗的目标 --我总觉得都是可鄙的. -- 爱因思坦" 上篇我们看了哈希表的相关定义和概念,这篇来看下如何来实现. 欢迎转载,转载请标明出处:http://blog.csdn.net/notbaron/article/details/47362781 1.  代码实现 1.1             Main 函数定义哈希元素数组 10个元素. 定义哈希表变量. 调用InitHashTable构造一个空的哈希表. 然后循

普通集合和泛型集合的区别,哈希表和字典表的区别,队列和堆栈的区别以及堆和栈的区别。

普通集合和泛型集合的区别: 泛型集合与传统集合相比 类型更安全. 泛型集合无需装箱拆箱操作. 泛型的重要性. 泛型是未来五年的主流技术 ... 通常情况下,建议您使用泛型集合,因为这样可以获得类型安全的直接优点而不需要从基集合类型派生并实现类型特定的成员.此外,如果集合元素为值类型,泛型集合类型的性能通常优于对应的非泛型集合类型(并优于从非泛型基集合类型派生的类型),因为使用泛型时不必对元素进行装箱. 下面的泛型类型对应于现有的集合类型: List 是对应于 ArrayList 的泛型类. Di

_DataStructure_C_Impl:哈希表

#include<stdlib.h> #include<stdio.h> typedef int KeyType; //元素类型定义 typedef struct{ KeyType key; //keyword int hi; //冲突次数 }DataType; //哈希表类型定义 typedef struct{ DataType *data; int tableSize; //哈希表的长度 int curSize; //表中keyword个数 }HashTable; //构造一个