我有一台有1mb内存的电脑,没有其他本地存储。我必须使用它通过TCP连接接受100万个8位十进制数字,对它们进行排序,然后通过另一个TCP连接发送排序的列表。

数字列表可能包含重复的,我不能丢弃。代码将放在ROM中,所以我不需要从1 MB中减去我的代码的大小。我已经有了驱动以太网端口和处理TCP/IP连接的代码,它需要2 KB的状态数据,包括1 KB的缓冲区,代码将通过它读取和写入数据。这个问题有解决办法吗?

问答来源:

slashdot.org

cleaton.net


当前回答

如果数字的范围是有限的(只能有2个8位数,或者只有10个不同的8位数),那么你可以编写一个优化的排序算法。但如果你想对所有可能的8位数进行排序,这在内存那么少的情况下是不可能的。

其他回答

到目前为止,这里还没有提到一个相当狡猾的技巧。我们假设您没有额外的方法来存储数据,但严格来说这并不正确。

解决问题的一种方法是做以下可怕的事情,任何人在任何情况下都不应该尝试:使用网络流量存储数据。不,我指的不是NAS。

你可以用以下方法对只有几个字节内存的数字进行排序:

首先取两个变量:COUNTER和VALUE。 首先将所有寄存器设置为0; 每次你收到一个整数I,增加COUNTER并将VALUE设置为max(VALUE, I); 然后向路由器发送数据集为I的ICMP echo请求报文。擦掉I,重复。 每次收到返回的ICMP包时,只需提取整数并在另一个回显请求中再次发送出去。这将产生大量的ICMP请求,其中包含整数。

Once COUNTER reaches 1000000, you have all of the values stored in the incessant stream of ICMP requests, and VALUE now contains the maximum integer. Pick some threshold T >> 1000000. Set COUNTER to zero. Every time you receive an ICMP packet, increment COUNTER and send the contained integer I back out in another echo request, unless I=VALUE, in which case transmit it to the destination for the sorted integers. Once COUNTER=T, decrement VALUE by 1, reset COUNTER to zero and repeat. Once VALUE reaches zero you should have transmitted all integers in order from largest to smallest to the destination, and have only used about 47 bits of RAM for the two persistent variables (and whatever small amount you need for the temporary values).

我知道这很可怕,我知道可能会有各种各样的实际问题,但我想这可能会让你们中的一些人发笑,或者至少会吓到你们。

如果输入流可以接收几次,这就容易多了(没有关于这方面的信息,想法和时间性能问题)。然后,我们可以数小数。有了计数值,就很容易生成输出流。通过计算值来压缩。 这取决于输入流中的内容。

在接收流时执行这些步骤。

首先设置一些合理的块大小

伪代码思想:

The first step would be to find all the duplicates and stick them in a dictionary with its count and remove them. The third step would be to place number that exist in sequence of their algorithmic steps and place them in counters special dictionaries with the first number and their step like n, n+1..., n+2, 2n, 2n+1, 2n+2... Begin to compress in chunks some reasonable ranges of number like every 1000 or ever 10000 the remaining numbers that appear less often to repeat. Uncompress that range if a number is found and add it to the range and leave it uncompressed for a while longer. Otherwise just add that number to a byte[chunkSize]

在接收流时继续执行前4步。最后一步是,如果超出内存,则失败,或者在收集完所有数据后开始输出结果,即开始对范围进行排序,并按顺序输出结果,然后按需要解压缩的顺序解压结果,并在得到它们时对它们进行排序。

我将利用TCP的重传行为。

让TCP组件创建一个大的接收窗口。 收到一定数量的包,但没有发送ACK。 处理这些传递,创建一些(前缀)压缩数据结构 对最后一个不再需要的数据包发送重复的ack /等待重传超时 转到2 所有数据包被接受

这假设了桶或多次传递的某种好处。

可能是通过对批次/桶进行排序并合并它们。->根树

使用这种技术接受并排序前80%,然后读取后20%,验证后20%不包含将落在最低数字的前20%的数字。然后发送最低的20%的数字,从内存中删除,接受剩下的20%的新数字并合并。**

您只需要按顺序存储数字之间的差异,并使用编码来压缩这些序列号。我们有2^23位。我们将它分成6位块,让最后一位表示这个数字是否扩展到另外6位(5位加上扩展块)。

因此,000010是1,000100是2。000001100000表示128。现在,我们考虑用最坏的类型来表示不超过10,000,000的数字序列的差异。可能有10000000 /2^5的差异大于2^5,10000000 /2^10的差异大于2^10,10000000 /2^15的差异大于2^15,等等。

所以,我们把表示这个序列所需要的比特数相加。我们有1,000,000*6 +汇总(10,000,000/2^5)*6+汇总(10,000,000/2^10)*6+汇总(10,000,000/2^15)*6+汇总(10,000,000/2^20)*4=7935479。

2^24 = 8388608。由于8388608 > 7935479,我们应该很容易有足够的内存。我们可能还需要一点内存来存储插入新数字时的和。然后我们遍历这个序列,找到插入新数字的位置,如果必要的话减少下一个差值,并将它之后的所有内容都右移。