C# 如何从合并排序中获取O(n log(n))?

C# 如何从合并排序中获取O(n log(n))?,c#,algorithm,sorting,mergesort,C#,Algorithm,Sorting,Mergesort,如何知道在链表上的合并排序实现中是否使用了O(nlog(n))。我应该向O(nlog(n))输入什么来了解我在合并排序上的实现时间 public static LinkedListNode<T> MergeSortLL<T>(LinkedListNode<T> Head) where T : IComparable<T> { if (Head?.Next == null) { return Head; }

如何知道在链表上的合并排序实现中是否使用了O(nlog(n))。我应该向O(nlog(n))输入什么来了解我在合并排序上的实现时间

public static LinkedListNode<T> MergeSortLL<T>(LinkedListNode<T> Head) where T : IComparable<T>
{

    if (Head?.Next == null)
    {
        return Head;
    }
    var middle = GetMiddle(Head);
    var half = middle.Next;
    middle.Next = null;

    Head = Merge(MergeSortLL(Head), MergeSortLL(half));
    return Head;
}

public static LinkedListNode<T> Merge<T>(LinkedListNode<T> Left, LinkedListNode<T> Right) where T : IComparable<T>
{

    var mHead = new LinkedListNode<T>(default(T));
    LinkedListNode<T> curr = mHead;

    while (Left != null && Right != null)
    {
        if (Left.Value.CompareTo(Right.Value) <= 0)
        {
            curr.Next = Left;
            Left = Left.Next;
        }
        else
        {
            curr.Next = Right;
            Right = Right.Next;
        }
        curr = curr.Next;
    }
    curr.Next = (Left == null) ? Right : Left;

    return mHead.Next;
}

public static LinkedListNode<T> GetMiddle<T>(LinkedListNode<T> Head) where T : IComparable<T>
{
    if (Head == null)
    {
        return Head;
    }

    LinkedListNode<T> slow, fast;
    slow = fast = Head;

    while (fast.Next?.Next != null)
    {
        slow = slow.Next;
        fast = fast.Next.Next;
    }
    return slow;
}
公共静态LinkedListNode MergeSortLL(LinkedListNode头),其中T:IComparable
{
if(Head?.Next==null)
{
回流头;
}
var middle=GetMiddle(头部);
var half=中间。下一步;
middle.Next=null;
Head=合并(合并SORTLL(Head),合并SORTLL(一半));
回流头;
}
公共静态LinkedListNode合并(LinkedListNode左侧,LinkedListNode右侧),其中T:IComparable
{
var mHead=新的LinkedListNode(默认值(T));
LinkedListNode curr=mHead;
while(左!=null和右!=null)
{

if(Left.Value.CompareTo(Right.Value)你能做的就是给你的排序方法添加一个计数器参数(一个引用),并在每次进入循环时增加它。然后你将这个计数器与你试图排序的元素的复杂度进行比较(我们称之为数量N)。然后你会看到你是在O(NlogN)中更多还是在O中更多(N²)


例如,当尝试对N=10个元素进行排序时,如果计数器为30,则
10*log(10)=23,02…和10²=100您可以看到您在O(NlogN)中比在O(N²)中更多。

请注意,已知此算法执行O(N*log(N))比较。如果您想确认这一点(因为它已被证明),您可以在每次比较中放置一个计数器并递增它

比如说

public static int Comparisons;

public static LinkedListNode<T> Merge<T>(LinkedListNode<T> Left, LinkedListNode<T> Right) where T : IComparable<T>
{
    // ...
    Comparisons++;
    if (Left.Value.CompareTo(Right.Value) <= 0)
    // ...
}
公共静态int比较;
公共静态LinkedListNode合并(LinkedListNode左侧,LinkedListNode右侧),其中T:IComparable
{
// ...
比较++;

如果(Left.Value.CompareTo(Right.Value))您需要分析您的算法。与N=256相比,您会循环多少次N=16的排序代码?例如,我的列表中有100个元素,我需要知道它将通过O(N*log(N)).O(N*log(N))循环多少次一个近似值不是一个函数来计算你的方法循环的确切次数。参见:Wiki有一个自下而上链表排序的例子,它避免了扫描列表来查找列表中间。wiki示例类似于微软C++ STL如何实现STD::List::SoR.To循环时需要增加2。(在merge method和GetMiddle中),然后,我需要比较n*log(n)的比较值和结果。我说得对吗?哎呀,我复制了错误的方法。我的意思是在发生
比较的方法中增加计数。
LinkedListNode<int> head = ...;
Comparisons = 0;
head = MergeSortLL(head);
Debug.Print(Comparisons);