简体   繁体   中英

How to get O(n log(n)) from merge sort?

How to get know if i'm using O(nlog(n)) in my merge sort implementation on linked list. What should I input to O(nlog(n)) to know that what the time of my implementation on merge sort.

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;
}

Please note that this algorithm is known to perform O(N*log(N)) comparisons . If you want to confirm that (because it's proven), you can put a counter and increment it on each comparison.

For instance

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)
    // ...
}

and checking it

LinkedListNode<int> head = ...;
Comparisons = 0;
head = MergeSortLL(head);
Debug.Print(Comparisons);

But note that this algorithm is also known to have a significant hidden cost (finding the middle, even with slow/fast pointer technique).

What you can do is add a counter parameter (a reference) to your sort method and increment it every time you enter in a loop. Then you compare this counter to the complexicity of the number of element you trying to sort (let's call that amount N). Then you will see if you are more in O(NlogN) or more in O(N²).


For exemple if your counter is 30 when trying to sort N =10 elements, as 10*log(10) = 23,02... and 10² = 100 you see that you are more in O(NlogN) than in O(N²).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM