Upload
tyrone-grant
View
212
Download
0
Embed Size (px)
Citation preview
Merge Sort
Stable vs. Non-Stable Sorts
We frequently use sorting methods for items with multiple keys
Sometimes we need to apply the sorting with different keys For instance we want to sort a list of people based on first name
and than on ageSo Black age 30 should appear before Jones age 30
If we sort a list based on the first key (name) and then apply a sort based on the second key (age) how can we guarantee that the list is still ordered based on the first key?
Definition:A sorting method is said the be stable if it preserves the relative
order of the items with duplicated keys on the list
An Example of a Stable Sort
Adams (30)
Washington (23)
Wilson (50)
Black (23)
Brown (40)
Smith (30)
Thompson (40)
Jackson (23)
White (50)
Jones (50)
Adams (30)
Washington (23)
Wilson (50)
Black (23)
Brown (40)
Smith (30)
Thompson (40)
Jackson (23)
White (50)
Jones (50)
Adams (30)
Black (23)
Brown (40)
Jackson (23)
Jones (50)
Smith (30)
Thompson (40)
Washington (23)
White (50)
Wilson (50)
Adams (30)
Black (23)
Brown (40)
Jackson (23)
Jones (50)
Smith (30)
Thompson (40)
Washington (23)
White (50)
Wilson (50)
Black (23)
Jackson (23)
Washington (23)
Adams (30)
Smith (30)
Brown (40)
Thompson (40)
Jones (50)
White (50)
Wilson (50)
Black (23)
Jackson (23)
Washington (23)
Adams (30)
Smith (30)
Brown (40)
Thompson (40)
Jones (50)
White (50)
Wilson (50)
Stable vs. Non-Stable Sorts
Mergesort is relatively easy to be made stable Just make sure the merge function is stable
Another algorithms that sort in O(n log n) is heapsort but it is not stable
Quicksort is also not stable
You need to understand which of the main sorting algorithms are stable and which ones are not.
Mergesort Quicksort is based on the idea of selecting an element
and dividing the list in two halves and then sorting the halves separately
We examine the complementary process which is called merging. Given two lists which are ordered combine them into a larger
ordered list Selection and merging are complementary because
Selection divides a list into two independent lists Merging joins two independent lists into one larger list
This should give a hint that Mergesort should consist of two recursive calls and one merging procedure
Mergesort The desirable features of Mergesort
It performs in O (n log n) in the worst case It is stable It is quite independent of the way the initial list is organized Good for linked lists. Can me implemented in such a way that
data is accessed sequentially Drawbacks
It may require an array of up to the size of the original listThis can be avoided but the algorithms becomes significantly more
complicated making it not worth whileInstead of making it complicated we can use heapsort which is also O(n
log n)
Understanding the Algorithm
1. Calculate the index of the middle of the list, called it m
2. Use recursion to sort the two partitions [first,m] and [m+1,last]
3. Merge the two ordered lists into one large list
1. Calculate the index of the middle of the list, called it m
2. Use recursion to sort the two partitions [first,m] and [m+1,last]
3. Merge the two ordered lists into one large list
Mergesort in C++
void mergesort(int theArray[], int first, int last) { // PRE: list is an array && // the portion to be sorted runs from first to last inclusive if (first >= last) // Nothing to sort return; int mid = (first+last)/2; // calculate the middle of the list
// Recursively call the two partitions mergesort(theArray,first,mid); mergesort(theArray,mid+1,last);
merge(theArrayt,first,mid,last);
// POST: list is sorted in ascending order between the first // and the last}
void mergesort(int theArray[], int first, int last) { // PRE: list is an array && // the portion to be sorted runs from first to last inclusive if (first >= last) // Nothing to sort return; int mid = (first+last)/2; // calculate the middle of the list
// Recursively call the two partitions mergesort(theArray,first,mid); mergesort(theArray,mid+1,last);
merge(theArrayt,first,mid,last);
// POST: list is sorted in ascending order between the first // and the last}
MergeSort Process
The list is divided into two equal ( as equal as possible) part.
There are different ways to divide the list into two equal part.
The following algorithm divides the list until the list has just one item which are sorted
Then with recursive merge function calls these smaller pieces merge.
Let’s see the algorithm in action.
Merge Sort in Action21 18 14 50 34 68 54 32 43 28 20
21 18 14 50 34 68 54 32 43 28 20
21 18 14 50 34 68 54 32 43 28 20
21 18 14
21 18
50 34
14 18 21 5034
14 18 21 5034
68 54 32 43 28 20
68 54 43 28
32 6854 20 28 43
54 6820 28 4332
14 18 21 54 6820 28 4332 34 50
On the performance of Mergesort Unlike quicksort, mergesort guarantees O(n log n) in
the worst case The reason for this is that quicksort depends on the value
of the pivot whereas mergesort divides the list based on the index
Why is it O (n log n)? Each merge will require N comparisons Each time the list is halved So the standard divide-and-conquer recurrence applies to
mergesort
T(n) = 2T * n/2 + (n)
Merge Sort Workhorse…Merge Function
void merge(int theArray[], int first, int last) { { tempArray[MAX_SIZE]; int first1 = first; int last1 = mid; int first2 = mid+1; int last2 = last; //while both arrays are not empty, copy the smaller item into the temp array int index = first1; //next available location in tempArray
for (; (first1 <= last1 && (first2 <= last2); ++index){ if (theArray[first1],theArray[first2]){ tempArray[index] = theArray[first1]; ++first1; } else{ tempArray[index] = the Array[first2]; ++first2; } } //finish off the first sub array, if necessary for (; first1 <= last1; ++first1; ++index) tempArray[index] = theArray[first1]; //finish off the first sub array, if necessary for (; first2 <= last2; ++first2; ++index) tempArray[index] = theArray[first2]; //copy result back into the original array for (index = first; index<= last; ++index) theArray[index] = tempArray[index];} //end merge
void merge(int theArray[], int first, int last) { { tempArray[MAX_SIZE]; int first1 = first; int last1 = mid; int first2 = mid+1; int last2 = last; //while both arrays are not empty, copy the smaller item into the temp array int index = first1; //next available location in tempArray
for (; (first1 <= last1 && (first2 <= last2); ++index){ if (theArray[first1],theArray[first2]){ tempArray[index] = theArray[first1]; ++first1; } else{ tempArray[index] = the Array[first2]; ++first2; } } //finish off the first sub array, if necessary for (; first1 <= last1; ++first1; ++index) tempArray[index] = theArray[first1]; //finish off the first sub array, if necessary for (; first2 <= last2; ++first2; ++index) tempArray[index] = theArray[first2]; //copy result back into the original array for (index = first; index<= last; ++index) theArray[index] = tempArray[index];} //end merge