Algorithm 如何在不保留整个数组且空间不变的情况下计算排序数组的精确中值?
我需要将排序数组从输入读取到awk/gawk,然后得到中值。我不想存储整个数组,我正在尝试获取用于计算的常量空间 你知道有什么算法能做到这一点吗?给定数组已排序,但其大小未知Algorithm 如何在不保留整个数组且空间不变的情况下计算排序数组的精确中值?,algorithm,awk,gawk,median,Algorithm,Awk,Gawk,Median,我需要将排序数组从输入读取到awk/gawk,然后得到中值。我不想存储整个数组,我正在尝试获取用于计算的常量空间 你知道有什么算法能做到这一点吗?给定数组已排序,但其大小未知 提前谢谢你 进行两次传递,使用第一次传递计算数组的大小,必要时将数据存储在文件中。否则,在不存储数组的情况下无法执行此操作,因为如果在读取n个项目后获取程序的状态,那么通过输入足够大的数字,您可以检索最后n/2个项目中的任何一个作为中位数,因此程序实际上必须至少记住这些项目。进行两次传递,使用第一个函数计算数组的大小,必要
提前谢谢你 进行两次传递,使用第一次传递计算数组的大小,必要时将数据存储在文件中。否则,在不存储数组的情况下无法执行此操作,因为如果在读取n个项目后获取程序的状态,那么通过输入足够大的数字,您可以检索最后n/2个项目中的任何一个作为中位数,因此程序实际上必须至少记住这些项目。进行两次传递,使用第一个函数计算数组的大小,必要时将数据存储在文件中。否则,在不存储数组的情况下无法执行此操作,因为如果在读取n项后获取程序的状态,那么通过输入足够大的数字,可以检索最后n/2项中的任意一项作为中位数,因此,程序实际上必须至少记住这些项。没有算法精确地找到使用固定内存量运行的未知长度排序序列的中值
看到这个,考虑这样的算法。假设它有一个长度为
N
的缓冲区,用于保存序列中的项目。在这个缓冲区满之前,算法只是简单地将项目放入其中,同时跟踪中间值
当算法扫描N+1
th项及其后的内容时,它必须在每个步骤中选择一个要删除的项目。假设它已经扫描了2N个
项目,删除了其中的一半。让我们假设它还没有降低输入流的中值
当扫描第项时,请考虑该项。应该放弃哪一项?它不能删除迄今为止保留的最小元素,因为输入可能在该项之后耗尽,在这种情况下,最低的可能是中位数。同样地,对于任何可能被删除的元素,输入序列都有一个未来,使该被删除的元素成为中间值
如果你愿意得到近似的结果,那么可能对你有用。没有算法可以精确地找到使用固定内存量运行的未知长度排序序列的中值
看到这个,考虑这样的算法。假设它有一个长度为
N
的缓冲区,用于保存序列中的项目。在这个缓冲区满之前,算法只是简单地将项目放入其中,同时跟踪中间值
当算法扫描N+1
th项及其后的内容时,它必须在每个步骤中选择一个要删除的项目。假设它已经扫描了2N个
项目,删除了其中的一半。让我们假设它还没有降低输入流的中值
当扫描第项时,请考虑该项。应该放弃哪一项?它不能删除迄今为止保留的最小元素,因为输入可能在该项之后耗尽,在这种情况下,最低的可能是中位数。同样地,对于任何可能被删除的元素,输入序列都有一个未来,使该被删除的元素成为中间值
如果您愿意获得近似结果,那么可能对您有用。基本上,您需要的是一个“算法”来查找数组的大小
N
,因为中位数将是元素数(N+1)/2
(现在忽略偶数/奇数细节)
我想不出一个算法不包含两个过程。根据定义,您需要第一次通过才能算出N
扫描元素i+1
时,可以保留以前i/2
元素的缓冲区。当到达数组的末尾时,中值将只是缓冲区中的第一个值,即只需要一次传递。这样做的问题是,您必须为缓冲区分配足够的内存以包含N/2
元素,但您不知道N
是什么,因此您不知道缓冲区应该有多大!另外,如果N
值太大而无法存储,如您在问题中所述,那么大概N/2
值也太大而无法存储(否则我的建议是:只需将RAM加倍)
因此,这种缓冲区方法不是一种选择。是两次传球。一个用来计算
N
,一个用来得到元素(N+1)/2
,基本上你需要的是一个“算法”来找到数组的大小N
,因为中位数是元素数(N+1)/2
(现在忽略偶数/奇数细节)
我想不出一个算法不包含两个过程。根据定义,您需要第一次通过才能算出N
扫描元素i+1
时,可以保留以前i/2
元素的缓冲区。当到达数组的末尾时,中值将只是缓冲区中的第一个值,即只需要一次传递。这样做的问题是,您必须为缓冲区分配足够的内存以包含N/2
元素,但您不知道N
是什么,因此您不知道缓冲区应该有多大!另外,如果N
值太大而无法存储,如您在问题中所述,那么大概N/2
值也太大而无法存储(否则我的建议是:只需将RAM加倍)
因此,这种缓冲区方法不是一种选择。是两次传球。一个用来计算
N
,一个用来获取元素(N+1)/2
,即使你不能存储数组,你能多次传递它吗?是的,我可以,但最好不要,因为数据量大,这会增加开销。如果你能多次传递它,那么就传递它来查找数组的大小,如果你不能,就查找medianEven