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)

No comments:

Post a Comment