二输入比较器实现排序算法
欢迎大家通过博客浏览我的历史文章,博客园包含了目前为止所有的文章,浏览效果更佳,并且有评论留言功能,有任何问题都可以给我留言,微信后台留言可能回复得不及时。
博客地址为:https://www.cnblogs.com/icparadigm/
面试题 - 二输入比较器实现排序算法
转载自
love小酒窝
https://www.cnblogs.com/lyc-seu/p/13385782.html
1. 问题描述
给定8个数,以及若干二输入的比较器(可以将两个输入排序)。要求在单周期内实现8个数的排序,并使用最少的比较器个数。(乐鑫)
(距离面试已经过了很久,抽空整理一下当时的题目)
2. 问题解析
乍一看,排序算法,这不是个算法题么,将8个数排下序,脑子里最先出来的是什么冒泡,选择,插入排序......赶紧打住,我们现在在讨论电路,不要走错片场了。实际上题目限定了二输入的比较器,所以方向很明确,现在已经有二输入排序模块,我们要用这个二输入的模块搭成8输入的。那么自然也就能想到,先搭个4输入的,看有没有什么规律。现在问题简化为4输入排序,很自然就想到,先分两组,每组之间排一下:(*表示较大的输出)
这样排完以后要解决的问题就是组间的大小问题。首先,两组之间最大的比较一下就能出来四个中最大的,两组最小的比较出来四个中最小的。所以第二级比较又需要两个比较器。第二级结束后我们已经得到了最大和最小,但次大和次小还不能确定,所以需要一个额外的比较器确定次大次小。所以四个数的排序电路如下:
所以4个数进行排序需要的最少的二输入比较器个数是5个。那么现在问题回到8个数,实际上我们相当于已经有了4输入进行排序的模块,用若干个4输入排序模块来完成8输入排序。相对于二输入模块,四输入的模块的输出可以分为两组,一组最大次大,另一组最小次小。实际上还是按照刚才的拓扑结构,将二输入换成四输入即可:
还是按照之前的思路,首先8个输入分为两组,每组之间排序。之后按照刚才的逻辑,上一组的最大次大和下一组的最大次大送入四输入排序模块,就可以确定出8个数中的最大和次大。这里可能有人会有疑问。假设如图中所示,第一层出来以后上面的模块输出最大次大是B和C,下面模块输出最大和次大是H和F,这四个数中一定会产生8个数中的最大和次大值么?答案是肯定的,因为对于A和D而言,B和C一定比他们大,所以没权利坐上8个里的第一第二的宝座,同理E和G也是。所以最大和次大值一定在B,C,H,F中产生。同理,最小和次小就会在A,D,H,F中产生。所以第二级结束后8个数中的最大,次大,最小, 次小就确定了。剩下四个再来一级比较一下就排序完成了。所以按照这种方法,8个数进行排序需要的二输入比较器个数就是5*5=25个。
经评论区@SpiritzQAQ君的提示,确实后面三个4输入模块没必要取完整,实际上可以只用4输入模块中的后三个二输入比较器,因为这几级的输入大小关系已经确定,更改后的拓扑图如下:
只需要5*2+3*3 = 19 个比较器。
3. 延伸思考
事实上,上面的硬件实现方式就是归并排序的展开实现,归并排序算法如下:
参考:https://www.cnblogs.com/onepixel/articles/7674659.html
归并排序是建立在归并操作上的一种有效的排序算法。该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为2-路归并。算法描述:
-
把长度为n的输入序列分成两个长度为n/2的子序列; -
对这两个子序列分别采用归并排序; -
将两个排序好的子序列合并成一个最终的排序序列。
再想一下,这一题最本质的问题其实是:
给定n个数的排序,最少需要的比较次数是多少?
如果从信息论的角度来看,n个数的排序总共有 种情况,对应的信息量就是 ,而一次比较获得的信息量 .所以理论的最少比较次数就是: 。可以发现当n=4时,理论比较次数为 , 向上取整就是5,跟我们的电路中用到的比较器个数相同。但是当n=8时,理论的最少比较次数是 ,也就是需要16次比较。那为什么我们这里用到了25个比较器呢?实际上这是因为题目限制了我们只能使用比较器,而要实现理论最小的比较次数还需要其他逻辑的支持,比如MUX。所以上述19个比较器只是归并排序算法的一种硬件实现方式,但并不一定是比较次数最少的硬件实现方式(考虑使用其他逻辑的话)。
PS: 5个数排序的理论最少排序次数(7)的一种比较逻辑:5个数排序最少比较次数[1]
使用这种方法推导8个数的最少比较次数可以得出最少需要18次,但仍然不是理论最少的。据说理论最少的比较次数并不一定能达到。
参考资料
5个数排序最少比较次数: https://blog.csdn.net/x_i_y_u_e/article/details/45059725?utm_medium=distribute.pc_relevant_t0.none-task-blog-BlogCommendFromMachineLearnPai2-1.edu_weight&depth_1-utm_source=distribute.pc_relevant_t0.none-task-blog-BlogCommendFromMachineLearnPai2-1.edu_weight
打个广告
路科验证V2课程大升级啦,升级后的V2pro,不仅保留了原本V2的所有内容,还添加了关于vim、linux、DVT的操作教程,以及寄存器模型自动化,更有定制的个性项目,为你的简历添砖加瓦。如果想要学习SV和UVM,想要入门或者转行验证,路科验证V2pro不容错过!如果对课程有兴趣可以后台联系我,可以获得优惠!详情戳->芯片验证V2 Pro秋季班报名通道已开启!更有早鸟报名优惠等着你!!
后台回复路科验证还可以享受200元优惠!!!欢迎报名~
精彩专辑
欢迎转发、在看、喜欢三连,关注公众号及时接收推送
个人博客地址:https://www.cnblogs.com/icparadigm/
点击在看,分享给你的朋友吧👇
本文分享自微信公众号 - 摸鱼范式(icparadigm)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
深挖 Redis 6.0 源码—— SDS
本文精选自 Doocs 开源社区旗下“源码猎人”项目,作者杨立滨。项目将会持续更新,欢迎 Star 关注。项目地址:https://github.com/doocs/source-code-hunter SDS(Simple Dynamic Strings, 简单动态字符串)是 Redis 的一种基本数据结构,主要是用于存储字符串和整数。这篇文章里,我们就来探讨一下 Redis SDS 这种数据结构的底层实现原理。 学习之前,首先我们要明确,Redis 是一个使用 C 语言编写的键值对存储系统。 前置思考 我们首先考虑一个问题,如何实现一个二进制安全的字符串? 在 C 语言中,\0表示字符串结束,如果字符串中本身就包含\0字符,那么字符串就会在\0处被截断,即非二进制安全;若通过使用一个 len 属性,来判断字符串是否结束,就可以保证读写字符串时不受到\0的影响,则是二进制安全。同时 len 属性也能保证在 O(1) 时间内获取字符串的长度。 Redis 3.2 以前的 SDS 实现 在 Redis 3.2 版本以前,SDS 的结构如下: struct sdshdr { unsigne...
- 下一篇
基于立体R-CNN的3D对象检测
点击上方“小白学视觉”,选择加"星标"或“置顶” 重磅干货,第一时间送达 好消息,小伙伴以后可以通过问答的形式在文章下方进行留言,并且小白也会及时回复大家哦! 双目立体视觉是机器视觉的一种重要形式,其原理是基于视差图像形成设备,使用从两个不同位置获取的物体图像,通过计算图像之间的对应点的位置偏差来获得三个对象的三维几何信息。 YOLO最初是由约瑟夫·雷德蒙(Joseph Redmon)创作的,用于检测物体。物体检测是一种计算机视觉技术,它通过在对象周围绘制边框并标识给定框也属于的类标签来对对象进行定位和标记。与大型NLP不同,YOLO设计得很小,可以为设备上的部署提供实时推理速度。 文献[1]提出了一种在立体图像方法中充分利用稀疏,密集,语义和几何信息的三维物体检测方法,称为立体R-CNN,用于自动驾驶。 Stereo R-CNN的网络体系结构将输出立体框,关键点,尺寸和视点角,然后输出3D框估计和密集3D框对齐模块。 Faster R-CNN扩展为立体信号输入,以同时检测和关联左右图像中的对象。稀疏的关键点,视点和对象尺寸是通过在三维区域提议网络之后添加其他分支来预测的,该分支网络与...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- Linux系统CentOS6、CentOS7手动修改IP地址
- Docker安装Oracle12C,快速搭建Oracle学习环境
- CentOS6,7,8上安装Nginx,支持https2.0的开启
- CentOS7设置SWAP分区,小内存服务器的救世主
- CentOS7编译安装Gcc9.2.0,解决mysql等软件编译问题
- Hadoop3单机部署,实现最简伪集群
- Docker快速安装Oracle11G,搭建oracle11g学习环境
- CentOS8,CentOS7,CentOS6编译安装Redis5.0.7
- SpringBoot2更换Tomcat为Jetty,小型站点的福音
- Windows10,CentOS7,CentOS8安装Nodejs环境