C# 使用快速排序对分数进行排序,并指定介于1/2和2/4之间

C# 使用快速排序对分数进行排序,并指定介于1/2和2/4之间,c#,quicksort,fractions,C#,Quicksort,Fractions,我正在尝试设置快速排序,并希望它对分数数组进行排序。 目前,它不会正确排序具有相等值的分数(例如1/2和2/4) 1/2必须在2/4之前,但它最终完全是随机的 我使用的代码是: public static void quicksort(Fraction[] f, int p, int r) { if (p < r) { int q = partition(f, p, r); quicksort(f

我正在尝试设置快速排序,并希望它对分数数组进行排序。
目前,它不会正确排序具有相等值的分数(例如1/2和2/4)
1/2必须在2/4之前,但它最终完全是随机的

我使用的代码是:

   public static void quicksort(Fraction[] f, int p, int r)
    {
        if (p < r)
        {
            int q = partition(f, p, r);
            quicksort(f, p, q - 1);
            quicksort(f, q + 1, r);
        }
    }

    public static int partition(Fraction[] f, int p, int r)
    {
        Fraction pivot = f[r];
        int i = p - 1;
        for (int j = p; j < r; j++)
        {
            if (f[j].Value < pivot.Value)
            {
                i++;
                Fraction wissel = f[i];
                f[i] = f[j];
                f[j] = wissel;
            }
            else
                if (f[j].Value < pivot.Value && f[j].Teller < pivot.Teller)
                {
                    i++;
                    Fraction wissel = f[i];
                    f[i] = f[j];
                    f[j] = wissel;
                }
        }
        Fraction wisselt = f[i + 1];
        f[i + 1] = f[r];
        f[r] = wisselt;
        return i + 1;

    }
公共静态void快速排序(分数[]f,int p,int r)
{
if(p
有人能解释一下怎么做吗


编辑:David Archer的建议解决了这个问题,谢谢大家。

我不确定您使用的是什么分数类,但如果您需要区分1/2和2/4(严格的数学术语是相等的),我建议您创建自己的比较方法,并使用这些方法,而不是内置的大于运算符和小于运算符

bool IsLessThan(Fraction a, Fraction b)
{
    // Your code here that results in 1/2 being less than 2/4
}

bool IsGreaterThan(Fraction a, Fraction b)
{
    // Your code here that results in 2/4 being greater than 1/2
}

为什么不直接使用
List.Sort()
?它是一个快速排序的实现。如果您有一个
IComparable
实现,那么您可以调用
Sort()
。如果要传递特定方法,也可以使用接受委托的重写

e、 g.如果你的
分数
课程是这样的:

    public class Fraction : IComparable<Fraction>
    {
     public int CompareTo(Fraction other)
     {
       // if other equals this, return 0
       // if other is greater than this, return -1
       // if other is less than this, return 1
     }
//...
    }
static int CompareFractions(Fraction a, Fraction b)
{
    // compare the value of the fractions
    int c = (a.numerator * b.denominator).CompareTo(a.denominator * b.numerator);
    if (c == 0)
        // break ties with "lowest numerator first"
        c = a.numerator.CompareTo(b.numerator);
    return c;
}

我认为你想要的比较是这样的:

    public class Fraction : IComparable<Fraction>
    {
     public int CompareTo(Fraction other)
     {
       // if other equals this, return 0
       // if other is greater than this, return -1
       // if other is less than this, return 1
     }
//...
    }
static int CompareFractions(Fraction a, Fraction b)
{
    // compare the value of the fractions
    int c = (a.numerator * b.denominator).CompareTo(a.denominator * b.numerator);
    if (c == 0)
        // break ties with "lowest numerator first"
        c = a.numerator.CompareTo(b.numerator);
    return c;
}

您也可以将其用作普通排序方法的排序委托。

您的问题是,您将快速排序设计为依赖于
,那么所有将一半与四分之二进行比较的代码都会说前者小于后者,这在排除此异常的所有上下文中都是错误的。Doh!你说得对。与其重载,不如将此逻辑本地化为快速排序。答案更新。如果我做得对的话,这将完全解决这个问题。该程序仅限于根据数组中的实例数执行快速排序或插入排序,因此它不会与程序的其余部分无关,除非你们两个遇到了我无法理解的更大的反对意见。如果该程序只是执行此排序,那两种方式都没有问题。如果你在用分数做其他事情,你希望1/2等于2/4,并且只希望这种排序用于排序,那么最好将逻辑本地化。用户可能希望这样一种奇怪的排序是框架的
排序
采用这种方法的两个原因之一。(另一个是重叠的情况,即人们可能希望对没有内置顺序的事物进行排序)。复制框架的方法。我强迫自己编写自己的快速排序算法,以便更好地理解高效的代码编写和算法的工作原理。首先,你需要定义如何比较不同的分数对象。然后,您需要在排序中执行该比较。您可以编写一个自行进行比较的排序,也可以将责任放在
Fraction
类上,让它实现
IComparable
,并在排序方法中简单地使用它。在任何情况下,如果没有看到你的
分数
类,没有人能真正为你提供更多细节。它已经解决了,但是如果你是中间人,我可以粘贴类分子*分母?不应该是/?@DavidArcher不。这是一个交叉乘法,一个分子和另一个分数的分母。啊,你说得对。这就是我在喝第二杯咖啡前阅读的收获。:)分数是一个具有3个属性的类,分数的上半部分、下半部分以及这两部分分开时的值。Teller、Noemer和Value,分别为。仅供参考,荷兰语Teller和Noemer的英文翻译分别为分子和分母。请发表评论。您可以定义自己的类
DelegateComparer
(可能应该是
DelegateComparer
),它保存一个
比较
委托,并使用该委托实现
IComparer
。这很好。只是想说,在即将发布的.NET4.5(VisualStudio2012)中,他们已经在框架中完成了这项工作。因此,在.NET4.5中,您可以说
Comparer.Create(cmp)
,然后像这样从
cmp
委托中获取您的
IComparer
。@JeppeStigNielsen您对
DelegateComparer
的看法是正确的。现在已经更正了,谢谢。该是他们公开这种方法的时候了——这是一种明显的需要,而且他们在幕后显然有一种方法,我想知道它是否在图书馆的某个地方,而我只是没有找到它!
public class Fraction
{
  public int Denominator{get;set;}
  public int Numerator{get;set;}
  public double Value
  {
    return (double) Numerator / (double) Denominator;
  }
}
private static int CompareSepDenom(Fraction x, Fraction y)
{
  int cmp = x.Value.CompareTo(y.Value);//normal comparison first
  if(cmp == 0)//same value;
    return x.Numerator.CompareTo(y.Numerator);//put lower numerator (also lower denum) first
  return cmp;
}
Array.Sort(arrayOfFractions, CompareSepDenom);
Array.Sort(arrayOfFractions, (x, y) =>
    {
      int cmp = x.Value.CompareTo(y.Value);//normal comparison first
      if(cmp == 0)//same value;
        return x.Numerator.CompareTo(y.Numerator);//put lower numerator (also lower denum) first
      return cmp;
    });
public static void QuickSort<T>(T[] arr, int p, int r, IComparer<T> cmp)
CompareTo(Fraction other)
{
  if(other == null)//take out this of Fraction is a struct
    return 1;
  return Value.CompareTo(other.Value)
}
CompareTo(object obj)
{
  if(other == null)
    return 1;
  Fraction fract = other as Fract;
  if(fract == null)
    throw new ArgumentException("Can only compare with other factions", "obj");
  return CompareTo(fract);
}