目录

一,遗忘比较交换算法

二,0-1排序引理

三,列排序

四,比较网络

1,比较算子

2,比较网络

3,比较网络的可并行性

五,排序网络

1,排序网络

2,排序网络的判定

3,冒泡排序的排序网络

4,希尔排序的排序网络

六,奇偶排序

1,奇偶排序网络

2,实现

七,双调排序

八,奇偶移项排序


一,遗忘比较交换算法

出自算法导论:

遗忘比较交换算法是指算法只按照事先定义好的操作执行,即需要比较的位置下标必须事先确定好。

虽然算法可能依靠待排序元素的个数,但它不能依靠待排序元素的值,也不能依赖任何之前的比较交换操作的结果。

在排序算法一文中有提到,插入排序、选择排序、冒泡排序、归并排序、堆排序、快速排序、希尔排序都是基于比较的排序,而这里面,冒泡排序是遗忘比较,希尔排序是嵌套了其他排序算法的,如果嵌套了遗忘比较算法,那么整个希尔排序也是遗忘比较算法,另外几个都不是遗忘比较算法。

二,0-1排序引理

0-1排序引理:如果一个遗忘比较交换算法能够对所有只包含0和1的输入序列排序,那么它也可以对包含任意值的输入序列排序。

三,列排序

即使不知道奇数步中,对每一列的排序采取的是什么排序算法,我们仍然可以认为,列排序算法是遗忘比较交换算法。

书中后面有提示,如何根据0-1排序引理证明上述八步操作可以完成排序,不难,略。

以s=5为例,我们把数组的长度补到50的倍数x(x>=250),那么r=x/5,r>=50,即满足条件,排序完成之后再把多余的元素删掉即可。

代码:

template<typename T>
void Sort(T* arr, int len, bool(*cmp)(T a, T b))
{   if (len < 250 || len % 50) {int b = max(len / 50, 5);int len2 = b * 50;T m = GetMax(arr, len);T* p = new T[len2];for (int i = 0; i < len; i++)p[i] = arr[i];for (int i = len; i < len2; i++)p[i] = m;Sort(p, len2, cmp);for (int i = 0; i < len; i++)arr[i] = p[i];return;}const int s = 5;int r = len / s;  //r行s列T* p = new T[len];for (int i = 0; i < len; i += r)Sort2(arr + i, r, cmp);//每一列排序for (int i = 0; i < len; i++) p[i / s + i % s * r] = arr[i];//转置for (int i = 0; i < len; i += r)Sort2(p + i, r, cmp);//每一列排序for (int i = 0; i < len; i++) arr[i] = p[i / s + i % s * r];//逆转置for (int i = 0; i < len; i += r)Sort2(arr + i, r, cmp);//每一列排序for (int i = r / 2; i < len - r; i += r)Sort2(arr + i, r, cmp);//最后一次排序
}

其中的sort2是调用别的排序算法,比如插入排序。

相关代码和接口定义参见 排序算法,下同。

四,比较网络

来自 OI之外的一些东西:简单谈谈排序网络 | Matrix67: The Aha Moments

1,比较算子

对于一个数列{ai},任取2个数ai和aj,比较大小并(可能)交换位置,使得ai<=aj成立,这样的一个操作叫比较算子。

PS:可以理解为这是递增比较算子,对应的还有一个递减比较算子。

2,比较网络

一系列有序的比较算子,构成一个比较网络。

例如下面是4个比较算子构成的网络:

一般的比较网络,所有的算子都是一个方向的,即要么都是递增算子要么都是递减算子,所以用图表示比较网络可以省略方向。

而对于既有递增算子又有递减算子的网络,需要用带箭头的线表示。

3,比较网络的可并行性

以上面的网络为例,中间的2个比较算子,如果改变先后顺序,或者说同时操作,显然整个网络的结果是一样的。

更一般地,如果把一个比较网络的若干比较算子的顺序交换,使得对于任意下标i,涉及到第i个元素的所有比较算子之间的前后顺序不变,那么整个网络就和原网络等价

PS:这是我的推理,没有严格的论证。

五,排序网络

1,排序网络

如果一个比较网络对于任何输入数列,输出的都是有序数列,那么称这个比较网络为排序网络。

上面的比较网络不是排序网络,如输入3 1 4 2输出的是1 3 2 4,不是有序的。

2,排序网络的判定

排序网络和遗忘比较交换算法是对应的。

所以判定一个比较网络是不是排序网络,可以用0-1排序引理。

即如果一个比较网络能够对所有只包含0和1的输入序列排序,那么它就是排序网络。

3,冒泡排序的排序网络

可以调整为:

这样,就可以提高并行程度,加快速度。

4,希尔排序的排序网络

希尔排序

六,奇偶排序

1,奇偶排序网络

不带浅色的是7个元素的排序网络,带浅色的是8个元素的排序网络。

排序网络一目了然,算法步骤就不用描述了。

matrix67的博文中用0-1排序引理和数学归纳法证明了此算法的正确性。

2,实现

template<typename T>
void Sort(T* arr, int len, bool(*cmp)(T a, T b))
{for (int i = 0; i < len; i++) {for (int j = i % 2; j + 1 < len; j += 2) {if (cmp(arr[j + 1], arr[j]))exchange(arr + j, arr + j + 1);}}
}

七,双调排序

双调就是单峰的意思。

1,双调排序网络

算法可以分为三块:

左上就是一个排序,和整个图是一样的。

左下和左上是对称的,也就是说,经过左边2个步骤之后,整个数列是单峰的。

右边的是把一个单峰数列变成一个有序数列。

2,实现

对于长度不是2的幂的数列,需要补齐长度。

template<typename T>
bool cmp2(T a, T b, int dir)
{if (dir == 0)return cmp(a, b);else return cmp(b, a);
}template<typename T>
void Sort(T* arr, int len, bool(*cmp)(T a, T b), int dir) // dir: 0 默认cmp 1 相反顺序
{if (len <= 1)return;Sort(arr, len / 2, cmp, dir);Sort(arr + len / 2, len / 2, cmp, 1 - dir);for (int k = 1; k < len; k *= 2) {int d = len / k;for (int s = 0; s < len; s += d) {for (int i = s; i < s + d / 2; i++)if (cmp2(arr[i + d / 2], arr[i], dir))exchange(arr + i + d / 2, arr + i);}}
}template<typename T>
void Sort(T* arr, int len, bool(*cmp)(T a, T b))
{int maxLen = 1;while (maxLen < len)maxLen *= 2;T* arr2 = new T[maxLen];T m = GetMax(arr, len);for (int i = 0; i < len; i++)arr2[i] = arr[i];for (int i = len; i < maxLen; i++)arr2[i] = m;Sort(arr2, maxLen, cmp, 0);for (int i = 0; i < len; i++)arr[i] = arr2[i];delete[]arr2;
}

3,等价形式

相当于把上面的网络的左下部分翻转一下,经过递归就得到方向一致的网络。

实现:

template<typename T>
void Sort2(T* arr, int len, bool(*cmp)(T a, T b))
{if (len <= 1)return;Sort2(arr, len / 2, cmp);Sort2(arr + len / 2, len / 2, cmp);for (int i = 0, j = len - 1; i < j; i++, j--) {if (cmp(arr[j], arr[i]))exchange(arr + j, arr + i);}for (int k = 2; k < len; k *= 2) {int d = len / k;for (int s = 0; s < len; s += d) {for (int i = s; i < s + d / 2; i++)if (cmp(arr[i + d / 2], arr[i]))exchange(arr + i + d / 2, arr + i);}}
}template<typename T>
void Sort(T* arr, int len, bool(*cmp)(T a, T b))
{int maxLen = 1;while (maxLen < len)maxLen *= 2;T* arr2 = new T[maxLen];T m = GetMax(arr, len);for (int i = 0; i < len; i++)arr2[i] = arr[i];for (int i = len; i < maxLen; i++)arr2[i] = m;Sort2(arr2, maxLen, cmp);for (int i = 0; i < len; i++)arr[i] = arr2[i];delete[]arr2;
}

八,奇偶移项排序

1,算法思路

奇偶移项排序和归并排序类似,差别在于合并过程是遗忘算法,所以整个排序是遗忘算法。

奇偶移项排序和双调排序一样,首先补齐元素,使得元素个数是2的幂,然后前面一半和后面一半递归排序,最后进行合并。

合并过程也是一个递归的过程,首先合并所有的奇数项,然后合并所有的偶数项,最后把所有的偶数项(除了最后一个)和它下一项比较交换,这样就完成了合并。

整个排序的时间复杂度是 O(n*logn*logn)

2,排序网络

以n=8为例:

3,实现

template<typename T>
void Merge(T* arr, int len, int d, bool(*cmp)(T a, T b))
{if (d >= len / 2) {if (cmp(arr[d], arr[0]))exchange(arr + d, arr);return;}Merge(arr, len, d * 2, cmp);Merge(arr + d, len - d, d * 2, cmp);for (int i = d; i < len - d; i += d * 2) {if (cmp(arr[i + d], arr[i]))exchange(arr + i + d, arr + i);}
}template<typename T>
void Sort2(T* arr, int len, bool(*cmp)(T a, T b))
{if (len <= 1)return;Sort2(arr, len / 2, cmp);Sort2(arr + len / 2, len / 2, cmp);Merge(arr, len, 1, cmp);
}

遗忘比较、排序网络、非常见排序相关推荐

  1. 常见排序算法详解 (收藏!)

    目录 冒泡排序 鸡尾酒排序 选择排序 插入排序 二分插入排序 希尔排序 归并排序 堆排序 快速排序 我们通常所说的排序算法往往指的是内部排序算法,即数据记录在内存中进行排序. 排序算法大体可分为两种: ...

  2. python常见排序算法解析

    python--常见排序算法解析 算法是程序员的灵魂. 下面的博文是我整理的感觉还不错的算法实现 原理的理解是最重要的,我会常回来看看,并坚持每天刷leetcode 本篇主要实现九(八)大排序算法,分 ...

  3. 十种常见排序算法欢聚一堂

    文章目录 1.常见排序算法分类 2.非线性时间比较类排序 2.1 交换类排序 2.1.1 冒泡排序 2.1.2 快速排序 2.2 插入类排序 2.2.1 直接插入排序 2.2.2 Shell 排序 2 ...

  4. ++代码实现 感知机的原理_常见排序算法原理及JS代码实现

    来源:SegmentFault 思否社区 作者:Warren 本文只是将作者学习的过程以及算法理解进行简单的分享,提供多一个角度的理解说明,或许让你的困惑能得以解决(代码或说明若有问题,欢迎留言.联系 ...

  5. 算法设计和数据结构学习_2(常见排序算法思想)

    一般约定我们是按照从小到大的顺序排序. 按照向量的形式来参考排序中数组元素的相对位置,行向量中最左边为数组的第一个元素,且称为前面.列向量中最上面的元素为数组的第一个元素,也是称为前边. 对常见的排序 ...

  6. js实现常见排序算法

    文章目录 前言 一.排序相关概念 1.比较排序和非比较排序 比较排序 非比较排序 2.稳定性和不稳定性 二.各排序算法对比 三.排序算法中的通用函数以及对数器 1.通用函数 交换函数 取两索引的中间下 ...

  7. 【十种常见排序算法】

    十种常见排序算法可以分为两大类: 比较类排序:通过比较来决定元素间的相对次序,由于其时间复杂度不能突破O(nlogn),因此也称为非线性时间比较类排序. 非比较类排序:不通过比较来决定元素间的相对次序 ...

  8. 常见排序算法之归并排序——归并排序

    哈喽大家好,我是保护小周ღ,本期为大家带来的是常见排序算法中的归并排序,博主在这里先分享归并排序的递归算法,包您一看就会,快来试试吧~ ​ 目录 一.归并排序 1.1 基本思想 1.2 算法思想 1. ...

  9. php常见排序算去,PHP兑现常见排序算法

    PHP实现常见排序算法 //插入排序(一维数组) function insert_sort($arr){ $count = count($arr); for($i=1; $i $tmp = $arr[ ...

最新文章

  1. 分布式任务分发框架Gearman测试、性能监控、队列持久化【python 实例】
  2. python简单代码画图-Python竟能画这么漂亮的花,帅呆了(代码分享)
  3. Part5核心初始化_lesson3---关闭看门狗
  4. 市值蒸发4460亿美元、股价下跌10%,苹果泡沫终于来了!
  5. linux模式匹配,sed的模式匹配用法探讨
  6. c语言文件分屏显示,通用子目录文件显示方法
  7. git如何选择性合并_小姐姐用 10 张动图,教会你 Git 命令使用
  8. oracle中视图窗粉色的,Oracle 11g日常操作与维护手册
  9. 这6大核心技能,程序员升职加薪的利器
  10. 跨库事务处理 spring+hibernate+struts2+jta
  11. Python基础——NaN(Not a Number)
  12. 带你认识不一样的Stream,Java8就该这么玩!
  13. matlab函数sinh,matlab sinh 使用方法
  14. whois域名查询工具在线使用
  15. pr关键帧动画、字幕、音频
  16. Centos7下新硬盘的挂载操作
  17. python上传钉钉媒体文件_python 上传钉钉图片
  18. Photoshop CC 2015安装激活
  19. win10如何停止自动更新
  20. Android Studio 4.0 Image Asset 图标不能透明(记录)

热门文章

  1. 【HDOJ 5399】Too Simple
  2. 微商引流海报怎么设置?什么样的海报更容易传播
  3. 如何在万能地图下载器内查看三维地形
  4. creo8.0 质量属性自动更新的设置
  5. Qt学习15:打包可执行文件.exe的两种方式
  6. 论文阅读SGD A Stochastic Approximation Method
  7. Spring Boot 自动配置原理再探
  8. vulmap——漏洞扫描工具简介与使用教程
  9. vue 限制手机端访问
  10. AI引领技术变革,自动化云平台所带来的测试工程师进阶危机~