散列表(离散链表法)

1.相关介绍

散列表也叫哈希表,英文名字Hash Table,有具体的哈希函数,将值映射到具体的表下标中。这样查找起来就十分方便。

散列表的注意点:

(1)散列函数要具有一致性,一个值通过散列表的映射得到的值是不变的,相同的值每次映射都是相同的结果。

(2)散列表中存的值,要均匀;如果值都聚集在一个位置,那么这个散列表就是糟糕的!

(3)填装因子应该小于0.7

填装因子=散列表中元素值个数/散列表中的总位置

当填装因子大于0.7时,需要进行调整!在满足装填因子的情况下,散列表中总位置尽量取素数,取上素数,发生冲突的概率小,但并不代表不发生!

哈希函数

目前我对哈希函数的理解,哈希函数本质上还是一个函数,就是你输入一个值,通过这个函数映射一个哈希表的索引下标;你把值存到哈希表中的话,你再次查找或者操作时,直接通过这个哈希函数,就可以立马找到!!!

方便快捷,哈哈!!

哈希函数1:输入参数1是字符串,参数2是散列表的大小

//将字符串中的字符的ASCII码相加
Index Hash1(char* Key,int TableSize)
{unsigned int HashVal=0;while(*Key!='\0'){HashVal+= *Key++; }return HashVal%TableSize;
}

哈希函数2

//u1s1,我不知道这是怎么想的
Index Hash2(char* Key,int TableSize)
{return (Key[0]+Key[1]*27+Key[2]*729)%TableSize;
}

哈希函数3

Index Hash3(char* Key,int TableSize)
{unsigned int HashVal=0;while(*Key!='\0'){HashVal=(HashVal<<5)+*Key++;    }return HashVal%TableSize;
}

2.散列表数据结构定义(关键)

#define MinTableSize (10)      //定义表的长度最小为10
typedef unsigned int Index;    //将unsigned int改名为Index
typedef int ElementType;       //将int改名为ElementType
struct ListNode{               //链表结构体定义,首先是数值,其次是指向下一个节点的指针ElementType Element;struct ListNode* Next;
};typedef  struct ListNode* Position;     //专门指链表的节点
typedef Position List;                  //专门指的是链表struct HashTbl{                         //哈希表的结构体定义int TableSize;                      //哈希表的尺寸List* TheLists;                     //相当于链表数组
};typedef struct HashTbl* HashTable;//这是正儿八经的哈希表 

数据结构图示:

3.散列表的相关操作

1.辅助函数:寻找一个最接近N的素数(大于等于N)
bool IsPrime(int n);
//参数N,返回一个大于等于N的素数
int NextPrime(int N)
{while(!IsPrime(N)){N++;  }return N;
}//判断一个数是否是素数
bool IsPrime(int n)
{for(int i=2;i*i<n;i++){if(n%i==0){return false;    }   }return true;
}

这个函数还让我回忆了一波,如何判断一个数是否为素数!

简单说一下:(1)时间复杂度为O(N)的定义判断法(2)时间复杂度为O(N^1/2)的优化方法,如上代码所示!!

2.对于输入数值,最简单的哈希函数设定
//很简单的Hash函数
Index Hash(ElementType Key,int TableSize)
{return Key%TableSize;
}
3.初始化哈希表

这个的关键便是:要清楚哈希表的数据结构构造。

首先,哈希表结构体包含哈希表长度和链表数组。链表数组中的每一个都是一个链表。

HashTable InitTable(int TableSize)
{HashTable H=(struct HashTbl*)malloc(sizeof(struct HashTbl));//想给哈希表搞一个素数长度了H->TableSize=NextPrime(TableSize);//在你定的哈希表长度的基础上,找一个最接近的素数值//开辟一个链表数组H->TheLists=(List*)malloc(sizeof(struct ListNode)*H->TableSize);       //给链表数组挨个开辟头结点空间 for(int i=0;i<H->TableSize;i++){H->TheLists[i]=(List)malloc(sizeof(struct ListNode));H->TheLists[i]->Next=NULL;}   return H;
}
4.在哈希表中查找一个值的节点位置
//在哈希表中寻找一个值所在的节点位置
Position Find(ElementType X,HashTable &H)
{List L=H->TheLists[Hash(X,H->TableSize)];//先找到值所在的链表数组索引,然后找到对应的链表Position p=L->Next;while(p!=NULL){if(p->Element!=X){p=p->Next;    }   }return p;
}

思路so easy!先通过哈希表寻找链表数组,在链表数组的每个元素(链表)中,依次遍历每一个链表节点,寻找这个值!

5.将值插入到哈希表中

思路:先将该值放入设定好的Hash函数中,求出这个值对应在Hash表中的索引,然后在链表数组中找到这个链表,再在这个链表的表头进行插入,OK!

//将一个值插入到哈希表中
//思路其实没个啥,其实就是给一个值,通过哈希函数映射到对应的链表数组索引,然后在对应的链表中进行表头插入
void Insert(ElementType X,HashTable H)
{Position p=Find(X,H);//如果存在,就不用管了//如果不存在,就在对应的表头进行插入Position NewCell;if(p==NULL){List L=H->TheLists[Hash(X,H->TableSize)]; NewCell=(struct ListNode*)malloc(sizeof(struct ListNode));NewCell->Element=X;NewCell->Next=L->Next;L->Next=NewCell;}
}
6.销毁哈希表

思路:先依次销毁链表数组中的各个链表,然后销毁链表数组名,最后销毁哈希表!

//销毁表
void  DestroyTable(HashTable H)
{Position p;for(int i=0;i<H->TableSize;i++){p=H->TheLists[i];  //瞎想,沿着这条链子,只要能找到各个节点就能删除了 while(p!=NULL){Position term=p->Next;free(p);p=term;}}free(H->TheLists);free(H);
}

散列表(离散链表法)相关推荐

  1. python实现散列表的链表法

    在散列中,链接法是一种最简单的碰撞解决技术,这种方法的原理就是把散列到同一槽中的所有元素 都放在一个链表中. 链接法有两个定理,定理一: 在简单一致散列的假设下,一次不成功查找的期望时间为O(1 + ...

  2. 20 | 散列表(下):为什么散列表和链表经常会一起使用?

    有两种数据结构,散列表和链表经常会被放在一起使用.常见的使用方式有: 用链表来实现 LRU 缓存淘汰算法,链表实现的 LRU 缓存淘汰算法的时间复杂度是 O(n),通过散列表可以将这个时间复杂度降低到 ...

  3. 【数据结构与算法】散列表

    一.散列表的由来? 1.散列表来源于数组,它借助散列函数对数组这种数据结构进行扩展,利用的是数组支持按照下标随机访问元素的特性. 2.需要存储在散列表中的数据我们称为键,将键转化为数组下标的方法称为散 ...

  4. 散列表(开放定址法)

    散列表(开放定址法) 1.线性探测法 将具体的值输入到哈希函数中,映射出的具体的哈希表中的下标索引.当下标索引冲突时. 离散链表法:将重复了的值用链表的方式挂在对应索引的链表下. 线性探测法:一个位置 ...

  5. 十、散列表(Hash Table)

    一.概述 散列表(Hash Table),也称"哈希表"或者"Hash 表" 1.相关概念 原始数据叫作键(键值)或关键字(key): 将原始数据转化为数组下标 ...

  6. 数据结构与算法(七)—— 散列表结构及其实现和应用

    注:本篇内容参考了<Java常用算法手册>.<大话数据结构>和<算法导论(第三版)>三本书籍.并参考了百度百科. 本人水平有限,文中如有错误或其它不妥之处,欢迎大家 ...

  7. 4021-基于链地址法的散列表的删除(C++,附思路)

    描述 请写出在散列表中删除关键字为k的一个记录的算法,设散列函数为H,H(key)=key%13,解决冲突的方法为链地址法. 输入 多组数据,每组三行,第一行为待输入的关键字的个数n,第二行为对应的n ...

  8. 4020-基于链地址法的散列表的插入(C++,附思路以及头插法,尾插法两种代码)

    描述 请写出在散列表中插入关键字为k的一个记录的算法,设散列函数为H,H(key)=key%13,解决冲突的方法为链地址法. 输入 多组数据,每组三行,第一行为待输入的关键字的个数n,第二行为对应的n ...

  9. 利用开放定址法实现散列表的创建、插入、删除、查找操作_散列表和IO

    散列表(也叫哈希表) 直接寻址法 取关键字或关键字的某个线性函数值为散列地址.即H(key)=key或H(key) = a·key + b,其中a和b为常数(这种散列函数叫做自身函数).若其中H(ke ...

最新文章

  1. Parasoft、SmartBear和Gimpel Software测试分析类产品对比评测
  2. flex 读取外部txt文件时候出现中文乱码现象
  3. 电脑反应慢卡怎么解决_电脑开不了机怎么解决?
  4. isulad代替docker_云原生时代的华为新“引擎”:iSula | Linux 中国
  5. 如何定义和实现一个类的成员函数为回调函数
  6. 旅途人物之二:幸福的孩子们
  7. C# 异步与Windows应用程序
  8. Qt--音乐播放器 V2.0
  9. UFLDL 教程学习笔记(二)反向传导算法
  10. android m版本 root,Android M或开放更多权限,root还需要吗?
  11. Java爬虫Jsoup篇
  12. redis 下载安装 python 操作redis django 连接redis
  13. 开优步认识各色各样的人,人生需要这样的新鲜体验!
  14. 房东拿租金去还房贷是天经地义的嘛
  15. java计算机毕业设计钢材出入库管理系统(附源码、数据库)
  16. 计算机excel怎么添加实线边框,Excel中自动添加边框线条的方法!学会效率翻倍!你确定不学?...
  17. python demo.py_pythonDemo.py
  18. 模拟通讯录系统2.0
  19. 事务,什么是事务,为何用事务?
  20. 红外粉尘传感器和激光粉尘传感器有什么区别?

热门文章

  1. 什么是“三次挥手”和“四次握手”
  2. R语言使用lm函数构建简单线性回归模型(建立线性回归模型)、拟合回归直线、使用residuls函数从模型中提取每个样本点的残差值、计算残差和和残差平方和
  3. UML统一建模语言学习总结
  4. 2021.11.22-11.28 AI行业周刊(第73期):工作的需求
  5. 判断一个IP是否CN2线路的最简单方法
  6. 利用css实现元素水平垂直居中的方法(分情况讨论)
  7. centos rpm安装iftop查看实时带宽
  8. 忆捷迷你硬盘更换图标e_40个出色的迷你图标集
  9. Swift - Selector
  10. win10移动热点无法设置