Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/sorting/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 复数排序_C#_Sorting_Struct - Fatal编程技术网

C# 复数排序

C# 复数排序,c#,sorting,struct,C#,Sorting,Struct,我在我的项目中有一个名为“Complex”的结构(我使用C#构建它),正如该结构的名称所暗示的,它是一个复数结构。这个结构有一个叫做“模数”的内置方法,所以我可以计算复数的模数。到目前为止,事情很容易 问题是,我用这个结构创建了一个数组,我想根据包含的复数的模对数组进行排序(从大到小)。有办法吗??(欢迎提出任何算法建议。) 谢谢 您始终可以使用SortedList:)假设模数为int: Complex[] complexArray = ... Complex[] sortedArray =

我在我的项目中有一个名为“Complex”的结构(我使用C#构建它),正如该结构的名称所暗示的,它是一个复数结构。这个结构有一个叫做“模数”的内置方法,所以我可以计算复数的模数。到目前为止,事情很容易

问题是,我用这个结构创建了一个数组,我想根据包含的复数的模对数组进行排序(从大到小)。有办法吗??(欢迎提出任何算法建议。)


谢谢

您始终可以使用SortedList:)假设模数为int:

Complex[] complexArray = ...

Complex[] sortedArray = complexArray.OrderByDescending(c => c.Modulus()).ToArray();
var complexNumbers = new SortedList<int, Complex>();
complexNumbers.Add(number.Modulus(), number);
var complexNumbers=new SortedList();
complexNumbers.Add(number.modules(),number);

假设模数为int,则始终可以使用SortedList:)

var complexNumbers = new SortedList<int, Complex>();
complexNumbers.Add(number.Modulus(), number);
var complexNumbers=new SortedList();
complexNumbers.Add(number.modules(),number);

首先,您可以通过比较平方模而不是模来提高性能。 您不需要平方根:“sqrt(a*a+b*b)>=sqrt(c*c+d*d)”相当于“a*a+b+b>=c*c+d*d”

然后,您可以编写一个比较器来对复数进行排序

public class ComplexModulusComparer :
    IComparer<Complex>,
    IComparer
{
    public static readonly ComplexModulusComparer Default = new ComplexModulusComparer();

    public int Compare(Complex a, Complex b)
    {
        return a.ModulusSquared().CompareTo(b.ModulusSquared());
    }

    int IComparer.Compare(object a, object b)
    {
        return ((Complex)a).ModulusSquared().CompareTo(((Complex)b).ModulusSquared());
    }
}
然后在你的代码中

Complex[] myArray ...;
myArray.SortReverseByModulus();
如果愿意,您也可以实现IComparable,但从我的观点来看,更正确、更正式的方法是使用IComparer

public struct Complex :
    IComparable<Complex>
{
    public double R;
    public double I;

    public double Modulus() { return Math.Sqrt(R * R + I * I); }

    public double ModulusSquared() { return R * R + I * I; }

    public int CompareTo(Complex other)
    {
        return this.ModulusSquared().CompareTo(other.ModulusSquared());
    }
}
我的机器是英特尔I5,64位Windows7。 很抱歉我在上一次编辑中做了一个愚蠢的小错误!
ARRAY.SORT输出LINQ,是的,输出量非常小,但正如所怀疑的,这个数量随着n的增加而增加,似乎不是以线性方式。在我看来,代码开销和内存问题(缓存未命中、对象分配、GC…不知道)。

首先,您可以通过比较平方模而不是模来提高性能。 您不需要平方根:“sqrt(a*a+b*b)>=sqrt(c*c+d*d)”相当于“a*a+b+b>=c*c+d*d”

然后,您可以编写一个比较器来对复数进行排序

public class ComplexModulusComparer :
    IComparer<Complex>,
    IComparer
{
    public static readonly ComplexModulusComparer Default = new ComplexModulusComparer();

    public int Compare(Complex a, Complex b)
    {
        return a.ModulusSquared().CompareTo(b.ModulusSquared());
    }

    int IComparer.Compare(object a, object b)
    {
        return ((Complex)a).ModulusSquared().CompareTo(((Complex)b).ModulusSquared());
    }
}
然后在你的代码中

Complex[] myArray ...;
myArray.SortReverseByModulus();
如果愿意,您也可以实现IComparable,但从我的观点来看,更正确、更正式的方法是使用IComparer

public struct Complex :
    IComparable<Complex>
{
    public double R;
    public double I;

    public double Modulus() { return Math.Sqrt(R * R + I * I); }

    public double ModulusSquared() { return R * R + I * I; }

    public int CompareTo(Complex other)
    {
        return this.ModulusSquared().CompareTo(other.ModulusSquared());
    }
}
我的机器是英特尔I5,64位Windows7。 很抱歉我在上一次编辑中做了一个愚蠢的小错误!
ARRAY.SORT输出LINQ,是的,输出量非常小,但正如所怀疑的,这个数量随着n的增加而增加,似乎不是以线性方式。在我看来,代码开销和内存问题(缓存未命中、对象分配、GC…不知道)都存在。

您能提供示例吗?对未排序的数组进行采样,然后对该数组进行排序。是否提供采样?对未排序的数组进行采样,然后对该数组进行排序。简短、简单、切中要害(尽管它实际上可能是一个方法调用-因为他们指出,
模数
是一个“内置方法”)。linq:)太多了。这比使用IComparer速度慢,而且消耗资源@SalvatorePreviti-LINQ可能比你认为的更聪明。例如,它将缓存计算的模数值。如果不在一个非常大的数据集上同时尝试这两种方法,就无法知道哪种方法更有效。实际上,你可能是对的,但当然,至少只有在比较平方模的情况下。只涉及求和和和乘法的浮点运算通常非常快,并且可以通过JIT进行大量优化。平方根涉及更多耗时的计算。由于涉及更多内存(更多缓存未命中),此方法消耗更多内存,并且对于非常大的n数可能会降低缓存效率。简短、简单、切中要害(尽管它实际上可能是一个方法调用-因为他们指出,
是一个“内置方法”).太多了linq:)这比使用IComparer速度慢而且耗费资源@SalvatorePreviti-LINQ可能比你认为的更聪明。例如,它将缓存计算的模数值。如果不在一个非常大的数据集上同时尝试这两种方法,就无法知道哪种方法更有效。实际上,你可能是对的,但当然,至少只有在比较平方模的情况下。只涉及求和和和乘法的浮点运算通常非常快,并且可以通过JIT进行大量优化。平方根涉及更多耗时的计算。由于涉及更多内存(更多缓存未命中),此方法会消耗更多内存,并且对于非常大的n数,缓存效率可能会降低。LINQ版本只会为每个值计算一次模,而您的版本在每次比较这两个值时都会计算ModulesQured。我怀疑你的两个版本的性能不会有很大的不同。我还怀疑LINQ版本在某些输入大小上可能优于您的版本。在这种情况下,如果不尝试这两种方法,就无法知道。可能您是对的,但当然,对数组进行排序是O(n*logn),因此正好有n*logn(r*r+i*i)操作。由于现代处理器的运算速度非常快,我真的不知道实际上什么会更快。我们应该运行一个复杂而长期的测试。LINQ版本只会为每个值计算一次模,而您的版本在每次比较两个值时都会为这两个值计算ModulesQured。我怀疑你的两个版本的性能不会有很大的不同。我还怀疑LINQ版本在某些输入大小上可能优于您的版本。在这种情况下,如果不尝试这两种方法,就无法知道。可能您是对的,但当然,对数组进行排序是O(n*logn),因此正好有n*logn(r*r+i*i)操作。由于现代处理器的运算速度非常快,我真的不知道实际上什么会更快。我们应该进行一次复杂而漫长的测试。
public class ReverseComparer<T> :
    IComparer<T>
{
    private IComparer<T> comparer;

    public static readonly ReverseComparer<T> Default = new ReverseComparer<T>();

    public ReverseComparer<T>() :
        this(Comparer<T>.Default)
    {
    }

    public ReverseComparer<T>(IComparer<T> comparer)
    {
        this.comparer = comparer;
    }

    public int Compare(T a, T b)
    {
        return - this.comparer.Compare(a, b);
    }
}
Complex[] array ...;
Array.Sort(array, ReverseComparer<Complex>.Default);
Complex[] array ...;
Array.Sort(array, new ReverseComparer<Complex>(myothercomparer));
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;

namespace TestComplex
{
    class Program
    {
        public struct Complex
        {
            public double R;
            public double I;

            public double ModulusSquared()
            {
                return this.R * this.R + this.I * this.I;
            }
        }

        public class ComplexComparer :
            IComparer<Complex>
        {
            public static readonly ComplexComparer Default = new ComplexComparer();

            public int Compare(Complex x, Complex y)
            {
                return x.ModulusSquared().CompareTo(y.ModulusSquared());
            }
        }

        private static void RandomComplexArray(Complex[] myArray)
        {
            // We use always the same seed to avoid differences in quicksort.
            Random r = new Random(2323);
            for (int i = 0; i < myArray.Length; ++i)
            {
                myArray[i].R = r.NextDouble() * 10;
                myArray[i].I = r.NextDouble() * 10;
            }
        }

        static void Main(string[] args)
        {
            // We perform some first operation to ensure JIT compiled and optimized everything before running the real test.

            Stopwatch sw = new Stopwatch();

            Complex[] tmp = new Complex[2];
            for (int repeat = 0; repeat < 10; ++repeat)
            {
                sw.Start();
                tmp[0] = new Complex() { R = 10, I = 20 };
                tmp[1] = new Complex() { R = 30, I = 50 };
                ComplexComparer.Default.Compare(tmp[0], tmp[1]);
                tmp.OrderByDescending(c => c.ModulusSquared()).ToArray();
                sw.Stop();
            }

            int[] testSizes = new int[] { 5, 100, 1000, 100000, 250000, 1000000 };

            for (int testSizeIdx = 0; testSizeIdx < testSizes.Length; ++testSizeIdx)
            {
                Console.WriteLine("For " + testSizes[testSizeIdx].ToString() + " input ...");

                // We create our big array

                Complex[] myArray = new Complex[testSizes[testSizeIdx]];

                double bestTime = double.MaxValue;

                // Now we execute repeatCount times our test.

                const int repeatCount = 15;

                for (int repeat = 0; repeat < repeatCount; ++repeat)
                {
                    // We fill our array with random data

                    RandomComplexArray(myArray);

                    // Now we perform our sorting.

                    sw.Reset();
                    sw.Start();
                    Array.Sort(myArray, ComplexComparer.Default);
                    sw.Stop();

                    double elapsed = sw.Elapsed.TotalMilliseconds;
                    if (elapsed < bestTime)
                        bestTime = elapsed;
                }

                Console.WriteLine("Array.Sort best time is " + bestTime.ToString());

                // Now we perform our test using linq
bestTime = double.MaxValue; // i forgot this before
                for (int repeat = 0; repeat < repeatCount; ++repeat)
                {
                    // We fill our array with random data

                    RandomComplexArray(myArray);

                    // Now we perform our sorting.

                    sw.Reset();
                    sw.Start();
                    myArray = myArray.OrderByDescending(c => c.ModulusSquared()).ToArray();
                    sw.Stop();

                    double elapsed = sw.Elapsed.TotalMilliseconds;
                    if (elapsed < bestTime)
                        bestTime = elapsed;
                }

                Console.WriteLine("linq best time is " + bestTime.ToString());

                Console.WriteLine();
            }

            Console.WriteLine("Press enter to quit.");
            Console.ReadLine();
        }
    }
}
For 5 input ...
Array.Sort best time is 0,0004
linq best time is 0,0018

For 100 input ...
Array.Sort best time is 0,0267
linq best time is 0,0298

For 1000 input ...
Array.Sort best time is 0,3568
linq best time is 0,4107

For 100000 input ...
Array.Sort best time is 57,3536
linq best time is 64,0196

For 250000 input ...
Array.Sort best time is 157,8832
linq best time is 194,3723

For 1000000 input ...
Array.Sort best time is 692,8211
linq best time is 1058,3259

Press enter to quit.