
彼此之间或多或少的不同种类的数量保证超过一百种。 其中有一些算法的子组,它们彼此之间的差异极小,这与某些一般的主要思想相吻合。 实际上,在不同的年份中,不同的人重新提出了相同的分类,只是在基本信息上并不相同。
这样的算法思想比其他思想更常见。
每个元素
大约在应放置数组的位置输入。 事实证明,数组
几乎是有序的 。 对其应用按插入排序(对于处理几乎有序的数组最有效)或使用相同算法递归处理局部无序区域。

本文是在EDISON的支持下撰写的,EDISON为各种任务开发了广泛的解决方案:从在线尝试在多品牌商店的衣服上试穿的程序,到内河与海上船只之间的LED传输系统 。
我们喜欢算法理论! ;-)
要评估大约要放置该元素的位置,需要找出它与数组的平均元素有多少不同。 为此,您需要知道最小和最大元素的值,以及数组的大小。
排序后的数组应该具有真正的随机数据。 此方法的所有发明者都得出相同的公式:
k是数组中元素
A (
i )应该位于的近似位置
min ,
max-数组
A中最小和最大元素的值
大小 -数组
A中的元素数
这是一个大致的想法。 让我们看看该算法一次又一次地诞生。
排序所罗门王::所罗门排序
此方法(及其漂亮的名称)
由 V2008n 的用户于大约5年前提出。 一切都有时间,“扔石头的时间和收集石头的时间”(传道书中所罗门王的话)-在算法中,这正是发生的情况。 首先,借助公式,我们将元素分散在数组中的所需位置。 由于公式给出的不是精确的位置,而是近似的位置,因此,值彼此接近的几个元素会同时声明某些位置。 这些局部元素组按插入顺序排序,然后按最终顺序组装。
插值排序
再次引用同一位作者的话:“阳光下没有新事物。” 维基百科描述了通过插值进行的排序,可疑地使人联想到所罗门排序。 每个“石头堆”都是一个小的附加动态数组,具有相似重要性的元素位于其中。 主要区别在于,在“散布石头”之后,这些局部未排序的元素组不是通过插入进行排序,而是通过插值对自己进行排序(递归或循环)。
有序数组是离散数据集,可以将其视为某个未知函数的已知值的有限集。 实际上,从计算数学的角度来看,近似分布是插值。
JavaScript插值排序-环回Array.prototype.interpolationSort = function() { var divideSize = new Array(); var end = this.length; divideSize[0] = end; while(divideSize.length > 0) {divide(this);} function divide(A) { var size = divideSize.pop(); var start = end - size; var min = A[start]; var max = A[start]; var temp = 0; for(var i = start + 1; i < end; i++) { if(A[i] < min) { min = A[i]; } else { if(A[i] > max) {max = A[i];} } } if(min == max) { end = end - size; } else { var p = 0; var bucket = new Array(size); for(var i = 0; i < size; i++) {bucket[i] = new Array();} for(var i = start; i < end; i++) { p = Math.floor(((A[i] - min) / (max - min)) * (size - 1)); bucket[p].push(A[i]); } for(var i = 0; i < size; i++) { if(bucket[i].length > 0) { for(var j = 0; j < bucket[i].length; j++) {A[start++] = bucket[i][j];} divideSize.push(bucket[i].length); } } } } };
JavaScript插值排序-递归版本 Array.prototype.bucketSort = function() { var start = 0; var size = this.length; var min = this[0]; var max = this[0]; for(var i = 1; i < size; i++) { if (this[i] < min) { min = this[i]; } else { if(this[i] > max) {max = this[i];} } } if(min != max) { var bucket = new Array(size); for(var i = 0; i < size; i++) {bucket[i] = new Array();} var interpolation = 0; for(var i = 0; i < size; i++){ interpolation = Math.floor(((this[i] - min) / (max - min)) * (size - 1)); bucket[interpolation].push(this[i]); } for(var i = 0; i < size; i++) { if(bucket[i].length > 1) {bucket[i].bucketSort();}
直方图排序::直方图排序
这是通过插值进行排序的优化,它可以计算属于本地未排序组的元素的数量。 此计数使您可以将未排序的项目直接插入到结果数组中(而不是将它们分组到单独的小数组中)。
JavaScript条形排序 Array.prototype.histogramSort = function() { var end = this.length; var sortedArray = new Array(end); var interpolation = new Array(end); var hitCount = new Array(end); var divideSize = new Array(); divideSize[0] = end; while(divideSize.length > 0) {distribute(this);} function distribute(A) { var size = divideSize.pop(); var start = end - size; var min = A[start]; var max = A[start]; for(var i = start + 1; i < end; i++) { if (A[i] < min) { min = A[i]; } else { if (A[i] > max) {max = A[i];} } } if (min == max) { end = end - size; } else { for(var i = start; i < end; i++){hitCount[i] = 0;} for(var i = start; i < end; i++) { interpolation[i] = start + Math.floor(((A[i] - min) / (max - min)) * (size - 1)); hitCount[interpolation[i]]++; } for(var i = start; i < end; i++) { if(hitCount[i] > 0){divideSize.push(hitCount[i]);} } hitCount[end - 1] = end - hitCount[end - 1]; for(var i = end - 1; i > start; i--) { hitCount[i - 1] = hitCount[i] - hitCount[i - 1]; } for(var i = start; i < end; i++) { sortedArray[hitCount[interpolation[i]]] = A[i]; hitCount[interpolation[i]]++; } for(var i = start; i < end; i++) {A[i] = sortedArray[i];} } } };
插值标签排序
为了进一步优化开销,在此建议不要记住未排序组中具有相似重要性的元素的数量,而应仅使用True / False标志标记这些组的开始。 True表示该子组已经排序,而False表示尚未排序。
JavaScript标记的插值排序 Array.prototype.InterpolaionTagSort = function() { var end = this.length; if(end > 1) { var start = 0 ; var Tag = new Array(end);
插值标签排序(就地)
如果数组中元素的值没有重复且不均匀分布(粗略地说-如果排序后的数据像算术级数一样),那么您可以一次性进行排序,就地排序,而无需将元素移动到中间数组中。
在JavaScript中按插值排序并使用标签(就地) Array.prototype.InPlaceTagSort = function() { var n = this.length; var Tag = new Array(n); for(i = 0; i < n; i++) {Tag[i] = false;} var min = this[0]; var max = this[0]; for(i = 1; i < n; i++) { if(this[i] < min) { min = this[i]; } else { if(this[i] > max) {max = this[i];} } } var p = 0; var temp = 0; for(i = 0; i < n; i++) { while(Tag[i] == false) { p = Math.floor(((this[i] - min) / (max - min)) * (n - 1)); temp = this[i]; this[i] = this[p]; this[p] = temp; Tag[p] = true; } } };
Flash Sort :: Flashsort
曾几何时,我
写过有关排序的文章,它是诺伊伯特(Neubert)生物物理学教授于1998年发明的。
教授建议将元素分布到几个单独的类中(类成员资格由元素的大小确定)。 考虑到这一点,公式如下所示:
该公式表示的是
m-分配数组元素的类数,而不是Size(数组大小)。 该公式不会计算元素应该抛出的数组中的键,而是元素所属的类号。
这种排序还不错,因为这样可以节省更多内存。 元素的重新分布就位。 仅类的本地化是分开存储的(好吧,如果从不同的角度看,则属于特定类的元素数是分开存储的)。
好吧,其余都是同一首歌。
用Java排序Flash class FlashSort { static int n; static int m; static int[] a; static int[] l; public static void flashSort(int size) { n = size; generateRandomArray(); long start = System.currentTimeMillis(); partialFlashSort(); long mid = System.currentTimeMillis(); insertionSort(); long end = System.currentTimeMillis();
近似排序:: Proxmap排序
这种排序是这里提到的最古老的排序;它是由加利福尼亚大学的Thomas Standish教授于1980年提出的。 在外观上似乎有很大不同,但是如果仔细观察,一切都是一样的。
该算法以
命中(hit)的概念进行操作-
命中某个值,其值与数组的某些元素接近。
为了确定数组元素是否为命中,将
近似函数应用于该元素。
Standish教授对实数数组进行了排序。 逼近功能是将实数四舍五入为整数。
也就是说,例如,如果数组包含元素2.8、2、2.1、2.6等。 那么这些数字将大打折扣。
一般程序:
- 我们对每个元素应用一个近似函数,确定哪个命中对应于下一个元素。
- 因此,对于每个匹配,我们可以计算与此匹配相对应的元素数。
- 知道所有匹配项的元素数量后,我们确定数组中匹配项的位置(左侧边界)。
- 知道匹配的本地化后,我们确定每个元素的本地化。
- 确定元素的本地化之后,我们尝试将其插入数组中的位置。 如果该位置已被占用,那么我们将向右移动邻居(如果元素小于它们),以便为该元素腾出空间。 或在右边插入元素本身(如果它大于相邻元素)。
作为一种近似函数,您可以根据数组中数据的一般性质分配任何一个。 在这种排序的现代实现中,命中率通常不是通过小数部分确定的,而是使用我们最喜欢的公式确定的。
JavaScript近似排序 Array.prototype.ProxmapSort = function() { var start = 0; var end = this.length; var A2 = new Array(end); var MapKey = new Array(end); var hitCount = new Array(end); for(var i = start; i < end; i++) {hitCount[i] = 0;} var min = this[start]; var max = this[start]; for (var i = start+1; i < end; i++){ if (this[i] < min) { min = this[i]; } else { if(this[i] > max) {max = this[i];} } }
哈希排序插入排序::哈希排序
好吧,我们将以bobbyKdas
habraiser六年前
建议的算法结束我们的评论。 这是一种混合算法,其中除了分布和插入之外,还添加了合并。
- 将数组递归地分成两半,直到在某些步骤中,半子数组的大小达到最小大小(作者不超过500个元素)。
- 在最低的递归级别上,将熟悉的算法应用于每个半子数组-使用相同的公式,子数组内部会发生近似分布,并通过插入局部未排序的部分进行排序。
- 在将子阵列的两半排列后,它们合并。
- 当通过递归级别爬到最顶部时,当原始数组由两个半部分合并时,将重复点3(排序的半部分子数组的合并)。
按Java中的哈希插入排序 import java.util.Arrays; import java.util.Date; import java.util.Random; public class HashSort {
该公式本身称为哈希函数,用于近似分布的辅助数组称为哈希表。
参考文献
插值和直方图 ,
Flash ,
Proxmap
所罗门 ,
哈希表 ,
Flash系列文章:
近似排序出现在AlgoLab Excel应用程序中(在这种情况下,在初始未排序数组中,随机小数部分附加到整数之后)。 所罗门(Solomon)和Flash(Flash)已经存在很长时间了,但尚未实现插值,哈希和直方图。