C# 如何从数组中找到前几个值?
我有一个浮点值数组,需要这个值,更重要的是最大四个值的位置 我最初构建该系统是为了遍历数组,并以通常的方式找到最大值,方法是将当前位置的值与记录的最大值进行比较,并在最大值发生变化时更新位置变量。这是一个非常简单的O(n)算法,效果很好。后来我了解到,我不仅需要保留最高价值,还需要保留前三名或前四名。我扩展了相同的过程,将max复杂化为一个包含四个max的数组,现在代码很难看 它仍然有效,并且仍然足够快,因为只有少量的计算被添加到过程中。它仍然有效地遍历数组并检查每个值一次 我在MATLAB中使用一个排序函数来实现这一点,该函数返回两个数组,排序列表和附带的原始位置列表。通过查看前几个值,我得到了我所需要的。我正在将此功能复制到C#.NET 2.0程序中 我知道我可以对列表对象做类似的事情,列表对象有一个内置的排序例程,但我不相信它能告诉我原始位置,而这些正是我真正想要的 它一直工作得很好,但现在我发现自己想要第五个max值,并且看到重写max-tour-checker(到目前为止,它是if语句的一团乱麻)只会让它更难看。添加第五个级别会很好,也不会慢,但我想问问SO社区是否有更好的方法 对整个列表进行排序需要比我目前的方法多得多的计算,但我认为这不会是一个问题,因为列表“只有”一到两千个浮点数;因此,如果有一个排序例程可以返回原始位置,那将是理想的C# 如何从数组中找到前几个值?,c#,algorithm,arrays,max,C#,Algorithm,Arrays,Max,我有一个浮点值数组,需要这个值,更重要的是最大四个值的位置 我最初构建该系统是为了遍历数组,并以通常的方式找到最大值,方法是将当前位置的值与记录的最大值进行比较,并在最大值发生变化时更新位置变量。这是一个非常简单的O(n)算法,效果很好。后来我了解到,我不仅需要保留最高价值,还需要保留前三名或前四名。我扩展了相同的过程,将max复杂化为一个包含四个max的数组,现在代码很难看 它仍然有效,并且仍然足够快,因为只有少量的计算被添加到过程中。它仍然有效地遍历数组并检查每个值一次 我在MATLAB中使
作为背景,这个数组是对一个千字节的波形文件进行傅里叶变换的结果,因此最大值的位置对应于样本数据的峰值频率。我对前四名很满意,但我认为有必要真正收集前五名或前六名,以获得更准确的样本分类。我可以建议一种替代算法,您必须编写:) 使用大小为K的堆,其中K表示要保存的顶级元素的计数。将其初始化为原始数组的前K个元素。对于所有N-K元素,遍历数组,根据需要插入
proc top_k (array<n>, heap<k>)
heap <- array<1..k-1>
for each (array<k..n-1>)
if array[i] > heap.min
heap.erase(heap.min)
heap.insert(array[i])
end if
end for
proc top_k(数组、堆)
heap.min
heap.erase(heap.min)
heap.insert(数组[i])
如果结束
结束
你仍然可以使用你的列表想法——你放在列表中的元素可以是一个存储索引和值的结构;但仅根据值进行排序,例如:
class IndexAndValue : IComparable<IndexAndValue>
{
public int index;
public double value;
public int CompareTo(IndexAndValue other)
{
return value.CompareTo(other.value);
}
}
类索引和值:i可比较
{
公共整数指数;
公共双重价值;
公共整数比较(索引和值其他)
{
返回值.CompareTo(其他.value);
}
}
然后您可以将它们粘贴到列表中,同时保留有关索引的信息。如果您只保留列表中最大的m项,那么您的效率应该是O(mn)。我不知道您当前使用的是哪种算法,但我建议使用一种简单的算法。 承认您有一个浮点数组
f
,最大容量为capacity
对于数字,您可以执行以下操作:
int capacity = 4; // number of floats you want to retrieve
float [] f; // your float list
float [] max_so_far = new float[capacity]; // max so far
// say that the first 'capacity' elements are the biggest, for now
for (int i = 0; i < capacity; i++)
max_so_far[i] = i;
// for each number not processed
for (int i = capacity; i < f.length; i++)
{
// find out the smallest 'max so far' number
int m = 0;
for (int j = 0; j < capacity; j++)
if (f[max_so_far[j]] < f[max_so_far[m]])
m = j;
// if our current number is bigger than the smallest stored, replace it
if (f[i] > f[max_so_far[m]])
max_so_far[m] = i;
}
int-capacity=4;//要检索的浮点数
浮动[]f;//你的浮动名单
浮点数[]最大浮点数=新浮点数[容量];//到目前为止
//就目前而言,第一个“容量”要素是最大的
对于(int i=0;if[max_so_far[m]]
max_so_far[m]=i;
}
在算法结束时,将存储最大元素的索引
在max\u sou\u far
中
请注意,如果容量
值增加,它将比
备选方案,即在跟踪初始位置的同时对列表进行排序。
请记住,排序需要O(nlog n)比较,而此算法需要O(ncapacity)。另一个选项是使用快速选择。 快速选择返回列表中第k个元素的位置。获得第k个元素的位置和值后,检查列表并获取每个值小于/大于第k个元素的元素 我在这里找到了quick select的c#实现: 优点:
重复:Oi,我应该在发布之前搜索我问题的反面:)我想你的意思是“return value.CompareTo(other.value);”+1。非常好的解决方案,只需要O(nlogk)时间和O(k)空间。