我有我的初始数组(允许随机或重复),需要先进行排序,然后需要将已排序的数组返回到原始数组,并保留顺序。
Ex:
orig_array: char[512] = { 1, 2, 4, 1,3,5,a,b,c,........}
Sorted array: char[512] = { 1, 1, 2,2,3.....) ( using sorting algorithms )
Unsorting back to original order: { 1, 2,4,1,3,......}
我一直坚持如何将unsorting实现回创建它们的原始顺序。
关于我为什么要问的一些背景知识:
在不同的系统上完全取消数组。排序的阵列被发送到网络并由主机接收。必须保留原始数据。
我的两端都有压缩模块来压缩和解压缩数据。压缩模块是CPU昂贵的。我的想法是对已排序的数据序列进行压缩,不应占用大量CPU,并且应该非常快速地对两端进行加密和解密,从而降低整体延迟
答案 0 :(得分:4)
如果排序"in-place" - 也就是说,重新排序实际数组中的元素,则无法取消排序。遗憾。
相反,你可以排序" out-of-place",或者对数组中元素的指针数组进行排序(使用数组数据进行比较) - 保持原始数组不变。
另请参阅:维基百科上的In-place algorithms
答案 1 :(得分:2)
如果不保留其他数据,则无法撤消排序。一种简单的方法是以原始顺序保留数据的副本,例如通过执行不合适的排序。这很快捷,但并不是唯一的选择。
你可以提供的反转过程的另一种方法(按@lurker)是按照执行顺序列出对阵列执行的更改(交换/置换),并通过向后执行反转列出并反转每个步骤。这相当简单,大约和原始排序一样快,但在平均情况下渐近限制需要更多内存而不仅仅是保留副本。
另一种方法是跟踪排序执行的元素排列。您可以通过创建元素索引的辅助数组来实现此目的,每个要排序的元素一个,最初按顺序排列。随着排序的进行,它会镜像每个元素移动,并在辅助数组中进行相应的移动。排序完成后,辅助数组会告诉您每个元素的原始索引是什么,并且您可以使用该信息将元素返回到原始顺序。这比保留原始数据的副本的内存效率低,并且可以在线性时间内执行订单恢复。
或者,您可以完全避免对原始数据进行排序。如果您改为对数据的指针数组进行排序,或者等效地对数据的索引进行排序,那么您可以在不丢失原始顺序的情况下找到排序的顺序。
答案 2 :(得分:1)
你说要排序和解压缩,因为数据需要在通过网络发送之前被压缩(这需要时间),并且压缩已排序的数据"应该"比压缩未分类的数据要快。
这听起来像是过早优化的情况。 "宜"更快的声音就像一个猜测。您应该测试压缩排序数据与压缩未排序数据以查看是否存在任何差异。您还需要考虑排序和未排序的时间。通过压缩排序列表,排序成本很可能会获得任何可能的收益。
即使您发现压缩排序数据的速度更快,也可能无关紧要。
这是解开的问题。
暂时忘记软件。假设我给你以下排序列表:
2 7 9 10 15 18 19 20 26 29
现在取消它。
你会怎么做?没有任何其他信息,就无法知道"适当的"订单是。它很可能已经开始排序,在这种情况下,它已经"未排序"。
至少,您需要知道列表未排序时每个值的位置。因此,如果未排序的列表如下所示:
10 9 26 29 18 2 20 7 19 15
您需要另一个列表,给出排序列表中每个值的原始索引:
5 7 1 0 9 4 8 6 2 3
但现在您有两个数字列表,因此您需要压缩和发送所需数据的大小翻倍。最重要的是,其中一个列表未分类。所以你回到了你开始的地方。
唯一可能获得的方法是原始列表中的项目不仅仅是数字而是大型聚合数据类型,因此索引列表与原始列表相比较小。在这种情况下,您可以将原始列表索引添加到数据类型以简化跟踪它。然后,您将再次测试压缩排序列表是否比未排序列表更快。但同样,压缩排序列表的速度更快的可能性很小,如果列表包含复杂数据类型则更是如此。
我的建议:只需压缩并发送未排序的列表。
答案 3 :(得分:0)
您可以在排序前创建原始数组的副本,也可以创建另一个指针数组和排序指针... 记忆不是问题,时间是,不要浪费更多时间去寻找不存在的魔法功能......