Lab 4: Abstract Classes And Sorting (5 Points)
Chris Tralie
Overview / Logistics
The purpose of this lab is to give you practice with the abstract classes and inheritance. In the process, you will also implement an algorithm to sort objects along a number line.
You can obtain the starter code by typing
git clone https://github.com/ursinus-cs174-s2023/Lab4_AbstractSorting.git
I have provided a makefile, and the entry point for running the code with a main
is in driver.cpp
Learning Objectives
- Separate out class specification from implementation between header files and cpp files, respectively
- Implement general code to implement algorithms that can apply to many specific types, using abstract classes
Background: Abstract Classes And Comparable Objects
Abstract Classes are classes that include pure virtual methods. The declarations look like this:
where the =0
is what causes this to be pure virtual. What this means is that we must override the class with a subclass that implements this method; we cannot use the abstract class by itself. Thus, we think of an abstract class as specifying a functionality that we would like inheriting objects to have. For this reason, abstract classes are often named as "something-able".
You will be working with an abstract class called Comparable
, which specifies the ability to compare two objects in a total order via the pure virtual method compareTo
. The method works as follows:
-
If
x.compareTo(y) < 0
, thenx < y
-
If
x.compareTo(y) == 0
, thenx = y
-
If
x.compareTo(y) > 0
, thenx > y
I've provided one class, CompInt
, which implements this method for int
variables. This class is a very thin wrapper class around an ordinary int
, and the compareTo
method is implemented quite simply as
The only trick here is that we have to cast other
to a CompInt*
type in order to access the field x
.
Task 1: getMinIndex
(1 Point)
One amazing thing we can do with abstract classes is to implement general purpose algorithms that can apply to many specific types. In our case, anything that is Comparable
can be put into what's known as a total order; put simply, we can order Comparable
objects along a number line.
To demonstrate this, fill in the definition of the getMinIndex
method in comparable.cpp
, which takes in an array of Comparable*
pointers, and which should return the index of the element which is smaller than all of the others, according to the total order induced by the compareTo
method. If there are ties, then it should return the smallest index.
As an example, I have setup an array of 10 CompInt*
references in driver.cpp
. The minimum index in that example should be 7
.
Task 2: CompString
String Wrapper (2 points)
To show off the generality of your code in the last part, create a class called CompString
that wraps around a C++ string and implements the compareTo
method to sort strings alphabetically. You can use the <
operator to compare char
components of each string. For example, you would find in C++ that 'a' < 'c'
evaluates to true
.
When you are finished, test your getMinIndex
method on an array of CompString*
references. As an example, suppose you had the following array of 10 CompString
objects
Then you should find that the minimum index is 4
, which corresponds to the string "college"
(note how "college" comes before "collegeville" in the alphabet).
Task 3: Insertion Sort (2 points)
In addition to findMinIndex
, create a void method sort
which puts the elements in a Comparable*
array into sorted order, using their compareTo
method. For this, you can use an algorithm known as insertion sort. The pseudocode for this algorithm is as follows:
If this works properly, then the strings in the example in task 2 should print in the following order after calling sort:
To help you understand better why insertion sort works, have a look at the following two videos below: