| CS 261 | University of Puget Sound | Spring, 2020 |
|
Computer Science II
|
||
|
Abstract Data Types and their Implementations,
Some Basic Algorithms,
Object-oriented Problem Solving, and Efficiency |
||
Warning:
This course is under development.
Although the basic structure of this course is largely established,
nothing on this Web site should be considered official or even possibly
correct.
DO NOT MAKE PLANS BASED ON THE CONTENTS OF THIS SITE UNTIL JANUARY, 2020.
The reading on the merge sort discussed an approach for sorting an array by successively merging small ordered arrays to get larger ordered arrays. The basic approach followed these steps:
When using arrays, we could access each array element immediately; we did not have to start at position 0 in the array and move element by element to get the nth item. Further, we could keep track of bounds of array segments in loops as part of the merge process. Pragmatically, we worked from array segments of size 1 and processed larger pieces as the algorithm progressed
Although we used iteration in the algorithm, recursion works just as well (perhaps more simply). The basic approach for a recursive algorithm starts with the large collection of data and recursive relies on calls to sort smaller collections: This approach is outlined as follows:
In code, this outline might proceed as follows when sorting items
within a list of ListNode elements:
public ListNode mergeSortLists (ListNode ls) {
/* handle base cases */
if ((ls == null) || (ls.getNext () == null)
{
return ls;
}
/* divide ls into two pieces of approximately equal size*/
ListNode sublist1 = ...
ListNode sublist2 = ...
/* sort both sublists*/
sublist1 = mergeSortLists (sublist1);
sublist2 = mergeSortLists (sublist2);
/* merge the two lists to get the sorted result */
return listMerge (sublist1, sublist2);
}
With this code outlined, the work remaining involves
This task can be handled in at least two ways, each of which requires a little care, but neither of which requires extensive coding.
Counting:
numb).
numb/2. At this
point,
sublist2 can point to the next node.
numb/2 can be
set to null.
sublist1 can now point to the first half of
the original list.
Overall with this approach, sublist1 references the
first half of the list, and sublist2 references the
second half of the list.
Alternating assignments:
sublist1 and then to the end
of sublist2
In following this approach, note that finding the end of a
sublist can be time consuming, if one starts at the beginning
each time. Thus, in this setting, we use sublist1
and sublist2 to keep track of the head of each
created list, and separate variables can keep track of the tail
of each list:
The reading on the merge sort presented the following outline for merging two sorted collections:
As long as items exist in both array segments:
Copy any remaining elements from the first array segment to the new array.
Copy any remaining elements from the second array segment to the new array.
Although work for this lab involves merging lists rather than arrays, the same outline applies—moving list nodes rather than array elements.
Create a mergeSortLists method within a list class,
such as NameList,
including the basic code structure identified above.
Use either the counting or alternating assignments method to split a list into two pieces of approximately equal size.
Write a method
ListNode mergeSortLists (ListNode sublist1, ListNode sublist2)
that follows the above outline to merge ordered two lists into one.
Note that completing the above three steps should yield a complete merge sort for lists!
Add some testing to your list class, so this merge sort algorithm can be tested appropriately.
|
created 1 February 2020 revised 2 February 2020 |
|
| For more information, please contact Henry M. Walker at walker@cs.grinnell.edu. |