我们之前所有的排序算法都是给定了数据再进行排序,排序的效率很大程度上取决于数据的好坏。我们今天所介绍的是一个完全不同的排序方法,它可以在“暗箱”里对数据进行排序(即你不必知道实际数据是什么),换句话说这种排序方法不依赖于数据(Data-Independent),所有比较操作都与数据无关。你甚至可以立即忘掉前面的比较结果,因为对于所有可能的数据这类排序算法都能得到正确答案并且排序步骤完全相同。本文结束后再回过头来看这段话你将有更深的认识。
我们设置一个暗箱,暗箱左边有n个输入口,暗箱右边有n个输出口。我们需要设计一个暗箱使得,任意n个数从左边输进去,右边出来的都是有序的。图1显示了有4个输入的暗箱。

暗箱里唯一允许的元件叫做“比较器”(Comparator),每个比较器连接两个元素,当上面那个比下面那个大时它将交换两个元素的位置。也就是说,每经过一个比较器后,它的两端中较小的一个总是从上面出来,较大的总是到了下面。图2显示了一种包含4个比较器的暗箱系统。当输入数据3,1,4,2通过这个系统时,输出为1,3,2,4,如图3所示。这种暗箱结构叫做比较网络(Comparator Network)。如果对于任意一个输入数据,比较网络的输出都是有序的,那么这个比较网络就叫做排序网络(Sorting Network)。显然,我们例子中的比较网络不是一个排序网络,因为它不能通过3,1,4,2的检验。
现在,我们的第一个问题是,是否存在比较网络。就是说,有没有可能使得任意数据通过同一组比较器都能输出有序的结果。我们最初的想法当然是,把我们已知的什么排序算法改成这种形式。把原来那十种排序又翻出来看一遍,找一找哪些排序的比较操作是无条件的。运气不错,我们所学的第一个算法——冒泡排序,它的比较就是无条件的,不管数据怎样冒泡排序都是不断比较相邻元素并把较小的放到前面。冒泡排序是一个彻头彻尾的排序网络模型,我们可以立即画出冒泡排序所对应的排序网络(图4)。这是我们得到的第一个排序网络。我们通常不认为插入排序是排序网络,因为插入排序的比较次数取决于数据的有序程度。

传统的计算机一次只能处理一个比较。排序网络真正的研究价值在于,假如有机器可以同时处理多个比较器,排序的速度将大幅度提高。我们把比较器的位置稍微移动一下,把那些互不冲突(处理的元素不同)的比较器压缩到一层(Stage)(图5),这样整个排序过程压缩为了2n-3层。实现排序网络的机器可以在单位时间里并行处理同一层中所有的比较。此时,比较次数的多少对排序效率不起决定作用了,即使比较次数多一些但是排序网络的层次更少,效率也会更高一些。我们自然又想,排序网络需要的层数能否少于2n-3。我们想到,图5的左下角和右下角似乎有些空,我们期望能在这些位置加一些比较从而减少层数。图6给出了一个只有n层的排序网络,这叫做奇偶移项排序(Odd-even Transposition Sort)。我们下文将证明它确实是一个排序网络。这次的图很多,排版也很困难,累死我了。我把下面的图7也放到这里来了,不然到处都是图很难看。

给出一个比较网络,怎样判断它是不是一个排序网络?很遗憾,现在还没有找到一种好的算法。事实上,这个问题是一个NPC问题。注:这种说法是不准确的,因为目前还没有迹象表明这个问题是NP问题。准确的说法应该是,“判断某比较网络为排序网络”是Co-NP Complete,而“判断某比较网络不是排序网络”(即找到一个反例)才是NP Complete。
传统的做法是枚举所有n的排列来验证,一共要考虑n!种情况。下面我们介绍排序网络理论里最重要的结论:0-1原理(0-1 Principle)。使用这个原理来验证排序网络只需要考虑2^n种情况。0-1原理告诉我们,如果所有的01序列能够通过比较网络排出顺序,那么这足以说明该网络为排序网络。证明过程很简单。为了证明这个结论,我们证明它的逆否命题(逆否命题与原命题同真假):如果一个比较网络不是排序网络,那么至少存在一个01序列不能被排序。我们给出一种算法,这个算法可以把任何一个不能被排序的输入数据转化为一个不能被排序的01序列。
在最初的例子(图3)中,输入数据3,1,4,2的输出为1,3,2,4,没有成功地排出顺序,从而判断出该网络不是排序网络。这说明,输出结果中存在逆序对(左边某个数大于右边的某个数)。我们从输出结果中找出一个逆序对来。例子中,(3,2)就是我们要找的数。现在,我们把输入中所有小于数字3(左边那个数)的数都变成0,把所有大于等于3的数都变成1。这样,3,1,4,2就变成了1,0,1,0。显然,把得到的这个01序列输入进去,原来曾经发生过交换的地方现在仍然会交换,原来不曾交换的地方现在也同样不会发生交换(当两个0或两个1进行比较时,我们既可以认为它们不交换,也可以看成它们要互相交换,反正都一样)。最后,该01序列输出的结果中,本来3的位置现在还是1,原来2的位置现在仍然是0,逆序对仍然存在。因此,只要一个比较网络不是排序网络,那么总可以找到一个01序列不能被排序。等价地,如果所有的01序列都能被排序了,这个比较网络也就是排序网络了。
我们用0-1原理来证明奇偶移项排序的正确性。我们对n进行数学归纳证明。n=2时(一个“工”字)显然是排序网络。
图中是n=8的情况。我们假设对于所有n<=7,奇偶移项排序网络都是正确的。我们同时假定所有输入数字非0即1,下面我们说明n=8时所有的01序列都能被正确排序。
假设最后一个数是1(图7,在前面的),那么这个1将始终排在最后不参与任何交换操作,对前面7个数没有任何影响。除去无用的灰色部分,剩下的就是n=7这一规模较小的子排序网络,由归纳假设则n=8也是排序网络;

假设最后一个数是0(图8),那么在每一次比较中这个0都会被提到前面去(前面说过,两个0之间交不交换是一回事)。蓝色的箭头表示每个数跑到了什么位置。你会发现除最后一个数以外前7个数之间的比较器又构成了n=7的情况。
接下来,我们提出一些比较器个数为O(n*logn*logn)的排序网络。其中一种就是之前提到过的2^p*3^q增量Shell排序。这种增量排序的特点是每一趟排序中的每个数只与前面的数比较一次,因此它可以非常方便地转化为排序网络。图9就是一个n=8的Shell排序网络。Bitonic排序也可以做到O(n*logn*logn)的比较器个数,今天不介绍它。下面详细介绍奇偶归并排序网络。

奇偶归并排序网络也是一种比较器个数为O(n*logn*logn)的排序网络。它和归并排序几乎相同,不同的只是合并的过程。普通归并排序的O(n)合并过程显然是依赖于数据的,奇偶归并排序可以把这个合并过程改成非数据依赖型,但复杂度将变高。这个合并过程本身也是递归的。我们假设n是2的幂(不是的话可以在前面添0补足,这对复杂度的计算没有影响),算法首先把n个数中所有的奇数项和偶数项分别递归地合并,然后在排序后的第i个偶数项和第i+1个奇数项之间设立比较器。
假如1,4,6,8和2,3,7,9是两段已经有序的子序列,合并过程首先递归地合并1,6,2,7和4,8,3,9,这样原数列就变成了1,3,2,4,6,8,7,9。然后分别把(3,2),(4,6),(8,7)三对相邻元素中各自较小的那个交换到前面,完成合并操作。使用0-1原理证明这个结论出乎意料的简单:图10显示了n=16的情况,白色的方格代表一个0,灰色方格代表1。奇偶项分别排序后,偶数项1的个数最多比奇数项多出2个,我们设立的比较器可以考虑到所有的情况,不管什么情况都能让它最终变得有序。

由前面说过的结论,合并过程总共需要比较O(nlogn)次。归并排序递归一共有O(logn)层,每一层总的比较器个数不超过O(nlogn),因此总共O(n*logn*logn)。一个n=8的完整的奇偶归并排序网络如图11所示。
菜鸟献丑,漏洞百出。如果我有什么错误,各位大牛请指正。
Matrix67原创,转载请注明出处。
外部排序(External Sort)已经在这里提到过,不再说了。
所有排序的知识到这里说完了,下次再发布的就是数论相关内容了。数论部分将从进位制开始谈起。
我会一直写下去,本人活到什么时候写到什么时候写完为止。不过,这几天缓一下,我计划做一个PJBlog的单版面论坛模块。
相关推荐
OI模板大全(普及~省选NOI)
hhh刚从某位大佬的洛谷首页偷到了一个好玩的东西 自己对照了一下原来我还有这么多东西没有学呜呜呜我好菜
奇偶排序
奇偶归并排序是Batcher在1968年提出。奇偶归并排序的作用主要是将两个有序序列合并成一个有序序列。 奇偶排序是冒泡排序的并行化版本,其基本思想是将冒泡排序中的每轮操作分解成奇数位上的比较交换和偶数位上的比较交换两部分,下面演示了奇偶排序的过程 原始数据 5 4 2 8 3 第一轮操作(奇数位) 4 5 2 8
省选辅导知识讲解目录:参加省选和NOI还需要哪些知识?
(一) NOIp结束后,我开始给我们学校高一高二的同学进行选拔赛辅导,时间是从12月11日到2月底,主要讲解NOIp以外的知识。期末考试的日期是2月1日,以这个日期为分界点可以把辅导分成两个阶段。前一阶段全部进行知识讲解,讲到了组合数学。这个阶段一星期上三次课,每个星期总计大概有8到9个课时。讲到1月24日后大家就回去准备期末考试了。后一阶段是在寒假中了,上了两个星期,模拟考
遗忘比较、排序网络、非常见排序
一,遗忘比较交换排序 出自算法导论: 遗忘比较交换算法是指算法只按照事先定义好的操作执行,即需要比较的位置下标必须事先确定好。 虽然算法可能依靠待排序元素的个数,但它不能依靠待排序元素的值,也不能依赖任何之前的比较交换操作的结果。 二,0-1排序引理 0-1排序引理:如果一个遗忘比较交换算法能够对所有只包含0和1的输入序列排序,那么它也可以对包含任意值的输入序列排序。 三,列排序 即使不知道奇数步中,对每一列的排序采取的是什么排序算法,我们仍然可以认为,列排序算法是遗忘比较交换..
避坑指南:C#用S7NetPlus读写西门子PLC字符串(String/WString)的完整方案
本文详细解析了C#通过S7NetPlus读写西门子PLC字符串(String/WString)的完整方案,包括内存布局、编码差异和字节序处理等关键技术细节。提供了实战优化的代码示例和常见问题排查指南,帮助开发者避免乱码、截断等常见陷阱,提升工业自动化项目的开发效率。
通达信强龙趋势幅图指标 - 精准捕捉趋势,把握强势行情,多角度分析个股,强弱一目了然
STICKLINE(趋势>0 AND SJTJ,4.8,5.8,1.5,0),COLORYELLOW;STICKLINE(资金>0 AND SJTJ,1.2,2.2,1.5,0),COLOR0080FF;STICKLINE(异动>0 AND SJTJ,0,1,1.5,0),COLORFF0080;STICKLINE(异动=0 AND SJTJ,0,1,1.5,1),COLORGRAY;
奇偶归并网络+SS-Mk算法(倾斜与震荡多路归并算法)
文章目录符号表示算法执行Sloping-and-Shanking Multiway Merging的描述 符号表示 有kkk个有序序列k≥2k\ge 2k≥2的任意素数 每个序列mmm个关键字 用m×km \times km×k的矩阵AAA来表示kkk个带归并的有序序列 0到k−10到k-10到k−1,0到m−10到m-10到m−1 列是有序序列哦 且非降 将矩阵AAA排成行为主的非降有...
用Python实现一个简单的远程桌面服务端和客户端
本文介绍了一个基于Python的轻量级远程桌面解决方案,针对商业软件在嵌入式系统上的兼容性问题、性能问题和成本问题。系统采用客户端-服务端架构,包含两个通信通道:5000端口传输压缩视频流,5001端口传输控制事件。通过多线程设计、图像压缩(JPEG+zlib)和网络优化(禁用Nagle算法)等技术手段提高性能。服务端实现了高效的屏幕捕获(使用mss库)、图像处理流水线和事件处理逻辑。客户端采用PyQt5构建UI界面,包含视频接收线程以减少主线程负担。该方案具有跨平台、开源免费、轻量级(核心代码不到500行
OI模板复习
NOIP常见模板
matlab 基于离散余弦变换DCT的最小二乘相位解缠
最小范数法是寻求在解包裹相位的局部微分与包裹相位微分相一致的条件下, 逼近于真实相位分布的解包裹相位分布。目标是使解包裹相位与包裹相位曲面的差最小
化工管道设计软件:CAESAR II二次开发_(6).API接口与函数库
自定义函数库是开发者根据特定需求编写的函数集合。这些函数可以扩展CAESAR II的功能,实现更复杂的管道设计任务。自定义函数库通常需要开发者具备一定的编程基础,能够理解和编写与CAESAR II接口兼容的代码。定义函数:在Python或其他编程语言中定义所需的函数。注册函数:将自定义函数注册到CAESAR II的函数库中。调用函数:在CAESAR II中调用自定义函数,实现特定功能。假设我们需要创建一个自定义函数库,用于批量修改管道节点的坐标。定义函数:在Python中定义一个函数,用于批量修改节点坐标。
OI 中一些可能有用的小 Trick 与注意点
持续更新,但是更新周期会比较长。 图论: 杂项: 树上边权转点权转移到儿子节点,但是特别注意多余信息处理(尤其是树剖的时候) 比如树剖结束的时候处理最后一条重链,最顶端节点的答案不能处理进去(因为会有多余信息 (topx,fatopx)(top_x,fa_{top_x})(topx,fatopx)) 还有一些计数题比如说统计路径上有多少个不同颜色的,注意一下根节点的多余数据处理(因为根节点是没有颜色的)。 看到图论题先想一下这几个问题:图是否连通?有向图还是无向图?是否带权?有没有重边与自环? 遇
高通开发系列 - Linux/Ubuntu移植到QCS8xxx平台
QCS8250和QRB5165平台属于体系架构相同的芯片,前置是带cellular而后者不带,即前置有移动网络而后者没有。 BSP部分的软件内容有差异需要修改外,同一套代码编译出来的执行程序是可以运行的,不会存在体系架构、指令集不匹配的问题。 QCS8250平台没有Linux/Ubuntu的软件SDK,只有Android的SDK,但是它对应j兼容的QRB5165平台有LE(Linux)和Ubun(Ubuntu)SDK。所以我们需要做的就是用QRB5165 Linux/Ubuntu移植到QCS8250平台上来
基于STM32设计的心率脉搏测量仪(项目资料ID:9)
本设计基于STM32F103单片机开发了一款便携式心率脉搏测量仪,通过光电传感器采集脉搏信号,经放大(约1200倍)、滤波(低通及四阶低通滤波)、比较及偏置电压调理后,由STM32进行ADC采样与数据处理。硬件采用Altium Designer设计,包含信号调理电路(限定心率范围43.4-800次/分钟)及电源管理模块;软件基于STM32CubeMX开发,利用队列存储和时间间隔平均算法优化精度,实现多终端显示(OLED实时心率/动画、MATLAB波形分析、蓝牙传输至手机)。系统支持自动启停(检测脉搏启
python基础知识补充
1. jupyter notebook 解释 2. ipython 魔法命令 3. latex in Markdown cell(在markdown里面编写数学公式) 4. jupyter notebook功能扩展:安装Nbextension 5. python解释与运行 6. 垃圾回收(计数机制与分代回收机制) 7. 名字空间与局部作用域L和全局作用域G 8. 小整数缓存区与字符驻留 9. Statement &Expression 10. 调试
[OI笔记]基础图论/图算法
[2017.8.29 00:00]——前几天开始好好学了几天的图论,不过这最近又突然因为一些原因(其实是晚上没睡好导致白天没精神)颓废了几天…一方面为了控制自己同时也可以当做之后noip前复习用的笔记,毕竟自学党的笔记只能这样子了吧。嗯,尽量写一些比较有用的东西以后自己方便复习也方便给新人看(我自己不还是新人么x),除了图算法其他一些内容之后学到也尽量开个博客记一下…嗯大概就这样 不定...
数学建模模型总结
这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!
记我一年的OI之路
upd:感觉没必要设密码了吧,把这个发出来还能显得自己弱颓一些。。 自从我刚刚接触c++,到现在已经快一年了吧,这一年中,我学到了很多,失去了很多,也得到了很多。 开通了blog,那就从现在,就是一个新的开始了吧,希望在接下来的学习中,能够继续进步,就算走的再慢,也要坚持走下去。 #include<iostream> using namespace std; int main() {...
Statistics and Machine Learning Toolbox
Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具
IEM模型,地表粗糙度模拟
利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟
OI国家集训队论文集1999~2018
直接放网盘: 链接:https://pan.baidu.com/s/1YqJmBVRd_ZNztU3EgW1RoQ 提取码:xj20 复制这段内容后打开百度网盘手机App,操作更方便哦 最重要的还是以上东西 以下图片和文字(没啥暖用,就是看起来整体清楚点)摘自别人博客:https://blog.youkuaiyun.com/qq_41551359/article/details/9396488...
老版QQ原生表情gif动态
这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。
道阻且长 莫失本心(我的OI之旅
道阻且长 莫失本心 今天午睡醒来,发现自己发烧了。尽管穿的很厚,尽管今天的阳光如此明媚。身体还是由内而外地散发着冷意。 期末考已经结束了,接下来又是艰难而难忘的奥赛训练。(要到春节才能放假了) 晚上来到机房一点效率都没有,硬撑着头皮学了LCT(动态树),还没有写模板题就来写博客了。 本来NOIP结束后,有过要退役的想法的,后来在JC(我们的奥赛教练)鼓舞下准备继...
GDSOI2019游记
不要问我这个菜鸡为什么可以来。我是锻炼选手。 Day -NaN 不知道从何说起。说远了又太多了,说近了又两句话就没了。 还是说近点吧,说远了又矫情了,根本写不下去。 开学不久收到官方通知,GD(S)OI要NOIP前100,轮不上我。 文化课方面压力挺大,还是选择了继续每周6节晚修泡机房。然而Ghastlcon/Ufowoqqqo/zyc/Monad都已经不上晚修甚至停课了。一开始接受不了,在教室晚...
2561



被折叠的 条评论
为什么被折叠?



