Algorithm
1. Divide the given unsorted list into n sublists, each containing 1 element (a list of 1 element is considered sorted).2. Repeatedly merge sublists to produce new sorted sublists until there is only 1 sublist remaining. This will be the sorted list.
Top-Down Approach
Basically the given list is split into sub-lists, until the run size is '1'. And then each sublist is merged to produce sorted list. Below is the c# version of top-down approach:
Code Snippet
- void TopDownMergesort(int[] a)
- {
- a.ThrowIfNull("a");
- int[] t = new int[a.Length];
- this.TopDownMergesort(a, t, 0, a.Length - 1);
- }
- void TopDownMergesort(int[] a, int[] temp, int start, int end)
- {
- if(start==end)
- {
- //run size of '1'
- return;
- }
- int mid = (start + end) / 2;
- this.TopDownMergesort(a, temp, start, mid);
- this.TopDownMergesort(a, temp, mid + 1, end);
- this.Merge(a, start, mid, end, temp);
- for(int i = start;i<=end;i++)
- {
- a[i] = temp[i];
- }
- }
- void Merge(int[] a, int start, int mid, int end, int[] temp)
- {
- int i = start, j = mid+1, k = start;
- while((i<=mid) && (j<=end))
- {
- if(a[i] <= a[j])
- {
- temp[k] = a[i];
- i++;
- }
- else
- {
- temp[k] = a[j];
- j++;
- }
- k++;
- }
- while(i<=mid)
- {
- temp[k] = a[i];
- i++;
- k++;
- }
- while (j <= end)
- {
- temp[k] = a[j];
- j++;
- k++;
- }
- Assert.IsTrue(k == end+1);
- Assert.IsTrue(i == mid+1);
- Assert.IsTrue(j == end+1);
- }
Bottom-Up Approach
Code Snippet
- void BottomUpMergesort(int[] a)
- {
- int[] temp = new int[a.Length];
- for (int runWidth = 1; runWidth < a.Length; runWidth = 2 * runWidth)
- {
- for (int eachRunStart = 0; eachRunStart < a.Length;
- eachRunStart = eachRunStart + 2 * runWidth)
- {
- int start = eachRunStart;
- int mid = eachRunStart + (runWidth - 1);
- if(mid >= a.Length)
- {
- mid = a.Length - 1;
- }
- int end = eachRunStart + ((2 * runWidth) - 1);
- if(end >= a.Length)
- {
- end = a.Length - 1;
- }
- this.Merge(a, start, mid, end, temp);
- }
- for (int i = 0; i < a.Length; i++)
- {
- a[i] = temp[i];
- }
- }
- }
Merging sorted lists (iterative)
Code Snippet
- LinkedListADTNode<int> MergeSortedLists(LinkedListADTNode<int> l1, LinkedListADTNode<int> l2)
- {
- if(l1 == null)
- {
- return l2;
- }
- if(l2 == null)
- {
- return l2;
- }
- var i1 = l1; var i2 = l2;
- LinkedListADTNode<int> firstNodeOfMergedList = null, currentNodeOfMergedList = null;
- while((i1 != null) && (i2 != null))
- {
- LinkedListADTNode<int> temp = null;
- if(i1.Element <= i2.Element)
- {
- temp = i1;
- i1 = temp.Next;
- }
- else
- {
- temp = i2;
- i2 = i2.Next;
- }
- if(firstNodeOfMergedList == null)
- {
- firstNodeOfMergedList = temp;
- }
- else
- {
- currentNodeOfMergedList.Next = temp;
- }
- currentNodeOfMergedList = temp;
- }
- while(i1 != null)
- {
- currentNodeOfMergedList.Next = i1;
- i1 = i1.Next;
- currentNodeOfMergedList = currentNodeOfMergedList.Next;
- }
- while(i2 != null)
- {
- currentNodeOfMergedList.Next = i2;
- i2 = i2.Next;
- currentNodeOfMergedList = currentNodeOfMergedList.Next;
- }
- return firstNodeOfMergedList;
- }
Merging sorted lists (recursive)
Code Snippet
- LinkedListADTNode<int> MergeSortedListsRecursive(LinkedListADTNode<int> l1, LinkedListADTNode<int> l2)
- {
- if(l1 == null)
- {
- return l2;
- }
- if(l2 == null)
- {
- return l1;
- }
- LinkedListADTNode<int> mergedList = null;
- if(l1.Element <= l2.Element)
- {
- mergedList = l1;
- mergedList.Next = this.MergeSortedListsRecursive(l1.Next, l2);
- }
- else
- {
- mergedList = l2;
- mergedList.Next = this.MergeSortedListsRecursive(l1, l2.Next);
- }
- return mergedList;
- }
Unit Tests
Code Snippet
- [TestMethod]
- public void MergeSortedListsTests()
- {
- LinkedListADT_Int l1 = new LinkedListADT_Int();
- LinkedListADT_Int l2 = new LinkedListADT_Int();
- for (int i = 1; i <= 15; i++)
- {
- if (i % 2 != 0)
- {
- l1.Add(i);
- }
- else
- {
- l2.Add(i);
- }
- }
- var ml = this.MergeSortedLists(l1.first, l2.first);
- var mi = ml;
- for (int i = 1; i <= 15; i++)
- {
- Assert.IsTrue(mi.Element == i);
- mi = mi.Next;
- }
- Assert.IsNull(mi);
- mi = ml = this.MergeSortedLists(null, l2.first);
- Assert.IsNotNull(ml);
- for (var i = l2.first; i != null; i = i.Next)
- {
- Assert.IsTrue(mi.Element == i.Element);
- mi = mi.Next;
- }
- Assert.IsNull(mi);
- mi = ml = this.MergeSortedLists(l1.first, new LinkedListADTNode<int>(6));
- Assert.IsNotNull(ml);
- }
Code Snippet
- [TestMethod]
- public void TopToBottomMergesortTests()
- {
- int[] a = { 13, 4, 1, 3, 8, 11, 9, 10 };
- this.TopDownMergesort(a);
- int[] b = { 1, 3, 4, 8, 9, 10, 11, 13 };
- Assert.IsTrue(a.Length == b.Length);
- for(int i = 0;i<a.Length;i++)
- {
- Assert.IsTrue(a[i] == b[i]);
- }
- List<int> l = new List<int>();
- for(int i = 10; i>=1; i--)
- {
- l.Add(i);
- }
- var la = l.ToArray();
- this.TopDownMergesort(la);
- for(int i =1; i<=10; i++)
- {
- Assert.IsTrue(la[i - 1] == i);
- }
- }
- [TestCategory(Constants.Arrays_Sorting)]
- [TestMethod]
- public void BottomUpMergesortTests()
- {
- int[] a = { 13, 4, 1, 3, 8, 11, 9, 10 };
- this.BottomUpMergesort(a);
- int[] b = { 1, 3, 4, 8, 9, 10, 11, 13 };
- Assert.IsTrue(a.Length == b.Length);
- for (int i = 0; i < a.Length; i++)
- {
- Assert.IsTrue(a[i] == b[i]);
- }
- List<int> l = new List<int>();
- for (int i = 10; i >= 1; i--)
- {
- l.Add(i);
- }
- var la = l.ToArray();
- this.BottomUpMergesort(la);
- for (int i = 1; i <= 10; i++)
- {
- Assert.IsTrue(la[i - 1] == i);
- }
- l.Clear();
- for (int i = 16; i >= 1; i--)
- {
- l.Add(i);
- }
- la = l.ToArray();
- this.BottomUpMergesort(la);
- for (int i = 1; i <= l.Count; i++)
- {
- Assert.IsTrue(la[i - 1] == i);
- }
- }