确定数组与目标数组的接近程度

时间:2012-10-06 05:43:37

标签: c# .net

我正在做一个小实验来增加我的知识,我已经达到了一个我认为我可以真正优化它的部分,但我不太确定如何做到这一点。

我有很多数字。 (为简单起见,假设每个数组都有4个数字:1,2,3和4)

  • 目标是按升序排列所有数字(即 1-2-3-4),但数字都在不同的数组中加扰。

  • 较大的数字会增加较高的重量。

  • 我需要按照它们的接近程度对所有这些数组进行排序 目标。

是的,4-3-2-1将是最糟糕的情况。

一些示例案例:

3-4-2-1 is better than 4-3-2-1
2-3-4-1 is better than 1-4-3-2 (even though two numbers match (1 and 3). 
                                the biggest number is closer to its spot.)

因此,大数字总是优先于较小的数字。这是我的尝试:

        var tmp = from m in moves
                  let mx = m.Max()
                  let ranking = m.IndexOf(s => s == mx)
                  orderby ranking descending
                  select m;

        return tmp.ToArray();

上面例子中的P.SindexOf是我写的一个扩展,用于获取数组和表达式,并返回满足表达式的元素的索引。这是必要的,因为情况确实有点复杂,我用我的例子简化它。

我在这里尝试的问题是,它只会按最大数字排序,而忘记所有其他数字。它应该首先按最大数量排名,然后按第二大排名,然后排在第三位。

此外,由于它会一遍又一遍地执行此操作几分钟,因此它应该尽可能高效。

2 个答案:

答案 0 :(得分:1)

您可以实施冒泡排序,并计算您必须移动数据的次数。在远离排序理想的阵列上,数据移动的数量会很大。

int GetUnorderedness<T>(T[] data) where T : IComparable<T>
{
    data = (T[])data.Clone(); // don't modify the input data, 
                              // we weren't asked to actually sort.
    int swapCount = 0;
    bool isSorted;
    do
    {
        isSorted = true;
        for(int i = 1; i < data.Length; i++)
        {
            if(data[i-1].CompareTo(data[i]) > 0)
            {
                T temp = data[i];
                data[i] = data[i-1];
                data[i-1] = temp;
                swapCount++;
                isSorted = false;
            }
        }
    } while(!isSorted);
}

从您的示例数据中,这将得到与您指定的略有不同的结果。

  

一些示例案例:
  3-4-2-1优于4-3-2-1
  2-3-4-1优于1-4-3-2

3-4-2-1将进行5次互换排序,4-3-2-1将需要6次,因此有效。
2-3-4-1将占用3,1-4-3-2也将占用3,因此这与您的预期结果不符。

此算法不会将最大数字视为最重要的数字,这似乎是您想要的;所有数字都得到平等对待。根据您的描述,您认为2-1-3-41-2-4-3更好,因为第一个数字在适当的位置包含最大和第二大数字。这个算法会认为这两个相等,因为每个只需要1个交换来对数组进行排序。

该算法的优势在于它不仅仅是一个比较算法,每个输入都有一个离散输出,所以你只需要为每个输入数组运行一次​​算法。

答案 1 :(得分:0)

我希望这会有所帮助

var i = 0;
var temp = (from m in moves select m).ToArray();
do
{
  temp = (from m in temp
         orderby m[i] descending
         select m).ToArray();
}
while (++i < moves[0].Length);