Showing posts with label Sorting. Show all posts
Showing posts with label Sorting. Show all posts

Saturday, July 26, 2014

Mergesort (arrays and lists)

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
  1. void TopDownMergesort(int[] a)
  2.         {
  3.             a.ThrowIfNull("a");
  4.             int[] t = new int[a.Length];
  5.             this.TopDownMergesort(a, t, 0, a.Length - 1);
  6.         }
  7.         void TopDownMergesort(int[] a, int[] temp, int start, int end)
  8.         {
  9.             if(start==end)
  10.             {
  11.                 //run size of '1'
  12.                 return;
  13.             }
  14.             int mid = (start + end) / 2;
  15.             this.TopDownMergesort(a, temp, start, mid);
  16.             this.TopDownMergesort(a, temp, mid + 1, end);
  17.             this.Merge(a, start, mid, end, temp);
  18.             for(int i = start;i<=end;i++)
  19.             {
  20.                 a[i] = temp[i];
  21.             }
  22.         }
  23.         void Merge(int[] a, int start, int mid, int end, int[] temp)
  24.         {
  25.             int i = start, j = mid+1, k = start;
  26.             while((i<=mid) && (j<=end))
  27.             {
  28.                 if(a[i] <= a[j])
  29.                 {
  30.                     temp[k] = a[i];
  31.                     i++;
  32.                 }
  33.                 else
  34.                 {
  35.                     temp[k] = a[j];
  36.                     j++;
  37.                 }
  38.                 k++;
  39.             }
  40.             while(i<=mid)
  41.             {
  42.                 temp[k] = a[i];
  43.                 i++;
  44.                 k++;
  45.             }
  46.             while (j <= end)
  47.             {
  48.                 temp[k] = a[j];
  49.                 j++;
  50.                 k++;
  51.             }
  52.             Assert.IsTrue(k == end+1);
  53.             Assert.IsTrue(i == mid+1);
  54.             Assert.IsTrue(j == end+1);
  55.         }
 

Bottom-Up Approach

 
Code Snippet
  1. void BottomUpMergesort(int[] a)
  2.         {
  3.             int[] temp = new int[a.Length];
  4.             for (int runWidth = 1; runWidth < a.Length; runWidth = 2 * runWidth)
  5.             {
  6.                 for (int eachRunStart = 0; eachRunStart < a.Length;
  7.                     eachRunStart = eachRunStart + 2 * runWidth)
  8.                 {
  9.                     int start = eachRunStart;
  10.                     int mid = eachRunStart + (runWidth - 1);
  11.                     if(mid >= a.Length)
  12.                     {
  13.                         mid = a.Length - 1;
  14.                     }
  15.                     int end = eachRunStart + ((2 * runWidth) - 1);
  16.                     if(end >= a.Length)
  17.                     {
  18.                         end = a.Length - 1;
  19.                     }
  20.                     
  21.                     this.Merge(a, start, mid, end, temp);
  22.                 }
  23.                 for (int i = 0; i < a.Length; i++)
  24.                 {
  25.                     a[i] = temp[i];
  26.                 }
  27.             }
  28.         }        

Merging sorted lists (iterative)

Code Snippet
  1. LinkedListADTNode<int> MergeSortedLists(LinkedListADTNode<int> l1, LinkedListADTNode<int> l2)
  2.         {
  3.             if(l1 == null)
  4.             {
  5.                 return l2;
  6.             }
  7.             if(l2 == null)
  8.             {
  9.                 return l2;
  10.             }
  11.             var i1 = l1; var i2 = l2;
  12.             LinkedListADTNode<int> firstNodeOfMergedList = null, currentNodeOfMergedList = null;
  13.             while((i1 != null) && (i2 != null))
  14.             {
  15.                 LinkedListADTNode<int> temp = null;
  16.                 if(i1.Element <= i2.Element)
  17.                 {
  18.                     temp = i1;
  19.                     i1 = temp.Next;
  20.                 }
  21.                 else
  22.                 {
  23.                     temp = i2;
  24.                     i2 = i2.Next;
  25.                 }
  26.                 if(firstNodeOfMergedList == null)
  27.                 {
  28.                     firstNodeOfMergedList = temp;
  29.                 }
  30.                 else
  31.                 {
  32.                     currentNodeOfMergedList.Next = temp;
  33.                 }
  34.                 currentNodeOfMergedList = temp;
  35.             }
  36.             while(i1 != null)
  37.             {
  38.                 currentNodeOfMergedList.Next = i1;
  39.                 i1 = i1.Next;
  40.                 currentNodeOfMergedList = currentNodeOfMergedList.Next;
  41.             }
  42.             while(i2 != null)
  43.             {
  44.                 currentNodeOfMergedList.Next = i2;
  45.                 i2 = i2.Next;
  46.                 currentNodeOfMergedList = currentNodeOfMergedList.Next;
  47.             }
  48.             return firstNodeOfMergedList;   
  49.         }

Merging sorted lists (recursive)

Code Snippet
  1. LinkedListADTNode<int> MergeSortedListsRecursive(LinkedListADTNode<int> l1, LinkedListADTNode<int> l2)
  2.         {
  3.             if(l1 == null)
  4.             {
  5.                 return l2;
  6.             }
  7.             if(l2 == null)
  8.             {
  9.                 return l1;
  10.             }
  11.             LinkedListADTNode<int> mergedList = null;
  12.             if(l1.Element <= l2.Element)
  13.             {
  14.                 mergedList = l1;
  15.                 mergedList.Next = this.MergeSortedListsRecursive(l1.Next, l2);
  16.                 
  17.             }
  18.             else
  19.             {
  20.                 mergedList = l2;
  21.                 mergedList.Next = this.MergeSortedListsRecursive(l1, l2.Next);
  22.             }
  23.             return mergedList;
  24.         }

Unit Tests

Code Snippet
  1. [TestMethod]
  2.         public void MergeSortedListsTests()
  3.         {
  4.             LinkedListADT_Int l1 = new LinkedListADT_Int();
  5.             LinkedListADT_Int l2 = new LinkedListADT_Int();
  6.             for (int i = 1; i <= 15; i++)
  7.             {
  8.                 if (i % 2 != 0)
  9.                 {
  10.                     l1.Add(i);
  11.                 }
  12.                 else
  13.                 {
  14.                     l2.Add(i);
  15.                 }
  16.             }
  17.             var ml = this.MergeSortedLists(l1.first, l2.first);
  18.             var mi = ml;
  19.             for (int i = 1; i <= 15; i++)
  20.             {
  21.                 Assert.IsTrue(mi.Element == i);
  22.                 mi = mi.Next;
  23.             }
  24.             Assert.IsNull(mi);
  25.             mi = ml = this.MergeSortedLists(null, l2.first);
  26.             Assert.IsNotNull(ml);
  27.             for (var i = l2.first; i != null; i = i.Next)
  28.             {
  29.                 Assert.IsTrue(mi.Element == i.Element);
  30.                 mi = mi.Next;
  31.             }
  32.             Assert.IsNull(mi);
  33.             mi = ml = this.MergeSortedLists(l1.first, new LinkedListADTNode<int>(6));
  34.             Assert.IsNotNull(ml);
  35.         }
Code Snippet
  1. [TestMethod]
  2.         public void TopToBottomMergesortTests()
  3.         {
  4.             int[] a = { 13, 4, 1, 3, 8, 11, 9, 10 };
  5.             this.TopDownMergesort(a);
  6.             int[] b = { 1, 3, 4, 8, 9, 10, 11, 13 };
  7.             Assert.IsTrue(a.Length == b.Length);
  8.             for(int i = 0;i<a.Length;i++)
  9.             {
  10.                 Assert.IsTrue(a[i] == b[i]);
  11.             }
  12.             List<int> l = new List<int>();
  13.             for(int i = 10; i>=1; i--)
  14.             {
  15.                 l.Add(i);
  16.             }
  17.             var la = l.ToArray();
  18.             this.TopDownMergesort(la);
  19.             for(int i =1; i<=10; i++)
  20.             {
  21.                 Assert.IsTrue(la[i - 1] == i);
  22.             }
  23.         }
  24.         [TestCategory(Constants.Arrays_Sorting)]
  25.         [TestMethod]
  26.         public void BottomUpMergesortTests()
  27.         {
  28.             int[] a = { 13, 4, 1, 3, 8, 11, 9, 10 };
  29.             this.BottomUpMergesort(a);
  30.             int[] b = { 1, 3, 4, 8, 9, 10, 11, 13 };
  31.             Assert.IsTrue(a.Length == b.Length);
  32.             for (int i = 0; i < a.Length; i++)
  33.             {
  34.                 Assert.IsTrue(a[i] == b[i]);
  35.             }
  36.             List<int> l = new List<int>();
  37.             for (int i = 10; i >= 1; i--)
  38.             {
  39.                 l.Add(i);
  40.             }
  41.             var la = l.ToArray();
  42.             this.BottomUpMergesort(la);
  43.             for (int i = 1; i <= 10; i++)
  44.             {
  45.                 Assert.IsTrue(la[i - 1] == i);
  46.             }
  47.             l.Clear();
  48.             for (int i = 16; i >= 1; i--)
  49.             {
  50.                 l.Add(i);
  51.             }
  52.             la = l.ToArray();
  53.             this.BottomUpMergesort(la);
  54.             for (int i = 1; i <= l.Count; i++)
  55.             {
  56.                 Assert.IsTrue(la[i - 1] == i);
  57.             }
  58.         }

Reference(s)