Algorithm 随机洗牌相等元素排序的比较方法

Algorithm 随机洗牌相等元素排序的比较方法,algorithm,language-agnostic,comparison,random,sorting,Algorithm,Language Agnostic,Comparison,Random,Sorting,这里有一个难题给你 我想改变下面的比较方法,这样当两个项目被认为相等时,它们将被随机洗牌 myList.Sort( (x, y) => x.Score.CompareTo(y.Score) ); 我可以想象,如果你不想在搜索结果得分相同的情况下优先选择一个结果而不是另一个结果,那么在排序搜索结果时,这个场景会很有用 有人想试一试吗 这是我第一次尝试解决问题,但没有成功。我会让你知道原因的 class RandomizeWhenEqualComparer<T> : ICompa

这里有一个难题给你

我想改变下面的比较方法,这样当两个项目被认为相等时,它们将被随机洗牌

myList.Sort( (x, y) => x.Score.CompareTo(y.Score) );
我可以想象,如果你不想在搜索结果得分相同的情况下优先选择一个结果而不是另一个结果,那么在排序搜索结果时,这个场景会很有用

有人想试一试吗

这是我第一次尝试解决问题,但没有成功。我会让你知道原因的

class RandomizeWhenEqualComparer<T> : IComparer<T>
{
    private readonly Func<T, T, int> _comparer;

    public int Compare(T x, T y)
    {
            if (x.Equals(y)) return 0;

        int result = _comparer(x, y);

        if (result != 0) return result;

        double random = StaticRandom.NextDouble();
        return (random < .5) ? -1 : 1;
    }

    public RandomizeWhenEqualComparer(Func<T, T, int> comparer)
    {
        _comparer = comparer;
    }
}
class RandomizeWhenEqualComparer:IComparer
{
专用只读函数比较器;
公共整数比较(TX,TY)
{
如果(x等于(y))返回0;
int结果=_比较器(x,y);
如果(result!=0)返回结果;
double random=StaticRandom.NextDouble();
回报率(随机<5)?-1:1;
}
公共随机化WhenequalComparer(函数比较器)
{
_比较器=比较器;
}
}

问题是比较的结果不能沿着排序进行复制。排序算法可以对给定的一对元素多次调用比较方法,每次比较方法都应返回相同的值


您可以存储涉及随机洗牌的每个比较的结果,并在对相应的对再次调用比较方法时查找它们。

首先随机洗牌,然后使用稳定的排序。

如果您只控制排序方法,那么您将受到严重限制,因为您不知道它将用于哪个排序算法。您必须保留相等键值之间任何比较的随机结果,并在表中查找相等值之间的任何新比较,以确保在任何单个排序运行中获得相同、稳定的结果,如Sharptooth所说


严格来说,这不是一种比较方法,但如果使用快速排序算法,您可以将关键点等于轴值的任何值随机化到哪个细分中呢?递归细分会随机地将一些相等的值放在左边,一些放在右边。

正如夏普顿所说,您可以存储每次比较的结果,然后再次查找它们

但这一点都不好玩,而且会增加时间复杂度和空间复杂度,因为您必须存储以前的比较,并在每次进行比较时搜索它们

下面是我要做的: 在搜索开始时,获取一个随机种子。 然后编写一个函数,该函数基于T和种子创建哈希

public int Hash(T a, int s)
{
    // e.g.
    return Random( a.Name().ToInt() + s ).NextDouble();
}

public int Compare(T x, T y, int s)
{
    if (x.Equals(y)) return 0;

    int result = _comparer(x, y);

    if (result != 0) return result;

    return (Hash(x, s) < Hash(y, s) ) ? -1 : 1;
}
public int Hash(ta,int s)
{
//例如。
返回Random(a.Name().ToInt()+s.NextDouble();
}
公共整数比较(tx,tys,ints)
{
如果(x等于(y))返回0;
int结果=_比较器(x,y);
如果(result!=0)返回结果;
返回值(散列(x,s)<散列(y,s))?-1:1;
}

这在给定的排序中是稳定的,但不需要查找表。

是的,这就是问题所在,现在解决方案是什么?这是一个优雅的解决方案。这确实意味着比较策略没有完全包含在比较类中,这对我来说并不理想,但无论如何它是好的?假设排序不知道关于要排序的元素的其他信息,除了它可以从比较方法中收集到的信息,当然这不重要…@Imran稳定性条件是充分的,但不是必要的。这取决于实现细节。例如,
newtreemap(newhashmap(input))
给出了不稳定的顺序,但输出不是随机的。是的,因此对比较方法有了明确的说明。我想知道如果你不能通过散列来“欺骗”是否重要找出为什么你建议做的是一个坏主意。如果比较器正确实现,并且在为同一对元素再次调用时返回相同的结果,这将不会是一个问题。啊,这就是我一直在寻找的出色解决方案的类型!将这一个标记为答案是因为,正如Geerad所说,其他的没有那么有趣,并且涉及到排序算法本身的更改,而不是将策略与比较算法隔离开来。