余数-取余操作就是哈希函数

今天学习的是余数,很常见的知识。

生活中的余数

在生活中有很多用到余数的例子,最常见的一周七天。譬如今天周六,那50天后是周几呢?

答案显而易见,50除以7得商7余数为1,在今天的基础上加1,50天后就是周日。这是日常生活中的例子,而在web编程中,我们有分页的概念,譬如有1234条数据,每页10条,请问需要多少页?1234除以10得商112余数4,那就是112页加上最后4条数据构成的1页,一共113页。

以上两个小例子,我们可以发现余数总是在一个固定的范围内。然而众所周知,整数是没有边界的,可余数却能够通过某一个种关系,让整数处于一个确定的边界。如上面的例子,一周七天让时间确定在了这周一到周日的7天中,假设今天是周一,那第8天、第15天还是周一,这些书除以7得到的余数都是一样的。这样一个现象被归纳总结为同余定理。

同余定理

同余定理,就是两个整数a和b,如果它们除以正整数m得到的余数相等,那就可以说a和b对于模m同余。

同余定理还有一个很常见的应用就是奇偶数,它的模也就是2,一个数除以2得余数为0,表示为偶数;一个数除以2得余数为1,表示为奇数。

同余定理的用途

同余定理可用来分类。对于无穷多的整数,同余定理帮助我们全面、多维度管理这些整数。因为不管模是多少,最终得到的余数肯定在一个确定的范围内。譬如,模为2,余数范围0-1;模为7,余数范围0-6。按照这个方式就能够把无穷多的整数分成有限个类。正是这一点,在计算机中是大有用途的。

哈希函数,将任意长度输入,通过哈希算法,压缩为某一固定长度的输出。这一思路和上面的同余定理如出一辙。

散列表(Hash table,也叫哈希表),是根据关键码值(Key value)而直接进行访问的数据结构。也就是说,它通过把关键码值映射到表中一个位置来访问记录,以加快查找的速度。这个映射函数叫做散列函数,存放记录的数组叫做散列表。

给定表M,存在函数f(key),对任意给定的关键字值key,代入函数后若能得到包含该关键字的记录在表中的地址,则称表M为哈希(Hash)表,函数f(key)为哈希(Hash) 函数。

举个例子,快速读写100万条数据记录。为达到告高速存取的最理想情况就是开辟一个连续空间存放,这样可减少寻址时间。但实际上无法满足如此大的连续空间来存放数据,这时,我们就可以用之前那个分页的概念。看系统中是否能提供若干个连续空间,每个空间又可以存放一定数量的记录,这些空间加起来就正好满足100万条记录。那么就可以使用余数和同余定理来设计一个散列函数,实现哈希表的结构。

首先,我们可以根据需求列出一个表达式:f(x) = x  mod  size

表达式中 x 表示等待被转换的100万条数据中的1条记录数值,mod 为取余操作,size 表示有限的存储空间大小。通过余数,可以将任何数值转化成有限范围内的数值,然后根据这个新的数值来确定记录应该存放在哪个空间。

假设,有限存储空间大小为100,那么就可以通过记录标号模100的余数指定某条记录存放在哪个空间。譬如有2条记录分别为1和101,它们模100之后的余数为1,让这样的记录存放在我们自定义为1的那个空间中,以此类推,记录2、102和202...余数为2的记录存放在2这个空间里。如此这样我们就能够得到求余的快速数字变化,对数据进行分组存放在不同的地址空间中。

除此之外,如果为了增加数据散列的随机程度,可以将公式转变为 f(x) = (x+MAX)  mod  size,其中MAX是较大的随机数。假设MAX是590199,那么针对标号为1的记录进行重新计算结果为0,而针对标号 101 的记录,如果随机数 MAX 取 627901,它的计算结果变成了2,这就与先前的情况不同了。这是因为加入了随机数MAX使得记录分配到同一空间中的情况更加“随机”,是适合数据重新洗牌的场景。譬如,加密算法。引入随机数可以增强加密算法的保密程度。

举个列子,加密一个三位数,设定这样一个加密规则:

  1. 先对三位数的个十百位的数加上个MAX
  2. 然后将每位上的数除以7,用所得到的余数替换掉原本的数
  3. 最后将百位和个位上的数互换位置

这里我们假设三位数是625,MAX为590127。那么百位上相加结果为590133,十位590129,个位590132,它们除以7得到的余数是百位上5,十位上1,个位上4,互换百位和个位,最终结果就是415。

这就是一个很简单的加密算法,把原本一个数通过加密变完全变个样,只有知道加密规则才可以通过反推得到原本的数。而这里面恰恰最重要的思想就是余数的运用。

 

关注我吧

关注「前端一起学」公众号 ,看着项目进阶学习,让我们一起学前端,一起进步。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
提供的源码资源涵盖了安卓应用、小程序、Python应用和Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。
好的,我来回答你的问题。 1. 哈希函数的设计及处理冲突的方法: 哈希函数可以采用取余法,即将关键字除以哈希表的长度,取余数作为该关键字在哈希表的位置。处理冲突的方法可以采用线性探测法,在发生冲突时,从当前位置向后寻找下一个空闲位置,直到找到为止。 2. 利用设计的哈希函数及线性探测法生成哈希表: 以下是一个简单的示例代码: ```c++ #include <iostream> using namespace std; const int MAX_SIZE = 10; // 哈希表的最大长度 int hashTable[MAX_SIZE] = {0}; // 哈希表,用0表示空闲位置 // 哈希函数,采用取余法 int hashFunc(int key) { return key % MAX_SIZE; } // 插入关键字到哈希表 void insert(int key) { int pos = hashFunc(key); // 计算关键字在哈希表的位置 while (hashTable[pos] != 0) { // 如果该位置已经被占用,发生冲突 pos = (pos + 1) % MAX_SIZE; // 采用线性探测法,从当前位置向后寻找下一个空闲位置 } hashTable[pos] = key; // 将关键字插入到哈希表 } // 查找关键字在哈希表的位置 int search(int key) { int pos = hashFunc(key); // 计算关键字在哈希表的位置 while (hashTable[pos] != key) { // 如果该位置不是要查找的关键字,发生冲突 pos = (pos + 1) % MAX_SIZE; // 采用线性探测法,从当前位置向后寻找下一个位置 if (hashTable[pos] == 0 || pos == hashFunc(key)) { // 如果遇到空闲位置或者回到原点,说明该关键字不存在 return -1; } } return pos; // 返回关键字在哈希表的位置 } // 输出哈希表的所有关键字 void print() { for (int i = 0; i < MAX_SIZE; i++) { if (hashTable[i] != 0) { cout << "位置 " << i << ": " << hashTable[i] << endl; } } } int main() { int choice, key; while (true) { cout << "1. 插入关键字" << endl; cout << "2. 查找关键字" << endl; cout << "3. 输出哈希表" << endl; cout << "4. 退出程序" << endl; cout << "请选择操作:" << endl; cin >> choice; switch (choice) { case 1: cout << "请输入要插入的关键字:" << endl; cin >> key; insert(key); break; case 2: cout << "请输入要查找的关键字:" << endl; cin >> key; if (search(key) == -1) { cout << "关键字不存在!" << endl; } else { cout << "关键字在哈希表的位置为:" << search(key) << endl; } break; case 3: print(); break; case 4: return 0; default: cout << "输入有误,请重新选择!" << endl; break; } } return 0; } ``` 3. 在主函数设计一个简单的菜单,调试上述算法: 以上示例代码已经包含了一个简单的菜单,可以直接运行调试。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值