(6) Sorting
Data Structures Using C++: Sorting Algorithms Study Notes
Objectives
Introduce the concepts of sorting.
Explain how the selection sort algorithm works and how it is implemented.
Explore how the insertion sort algorithm works and how it is implemented.
Explore how the merge sort algorithm works.
Compare the performance of the three algorithms.
Introduction to Sorting
Sorting is an operation on a data structure that means putting the elements of a list in order, typically to facilitate searching.
Ordered List: List whose elements are arranged according to a specific order.
Unordered List: List whose elements are not arranged in any particular order.
Types of Order
Alphabetical Order: For character or string data.
Numerical Order: For numerical data.
Ascending Order: From lowest to highest value.
Descending Order: From highest to lowest value.
Applications of Sorting
Sorting can be applied on:
Array-based lists
Linked lists (though less commonly utilized)
Files and indexes (key-based sorting)
Differences in Operations on Ordered vs Unordered Lists
Operations may differ significantly between unordered and ordered data structures.
For example, a search operation in an ordered list can cease once an element greater than the searched item is encountered.
Sorting Algorithms
Several sorting algorithms exist with varying time complexities, including:
Bubble Sort
Selection Sort
Insertion Sort
Quick Sort
Merge Sort
Efficiency of Searching in Sorted Lists
An ordered list facilitates more efficient searching methods:
Sequential Search: Can be performed on both ordered and unordered lists.
Binary Search: Can only be performed on sorted lists and is much more efficient than sequential search in this context.
Selection Sort
Selection sort works by selecting the smallest element from the list and moving it to its proper position in the sorted portion of the list.
Steps of the Selection Sort Algorithm
Initialize
i = 0.Find the location of the smallest element in the unsorted portion of the list (from
list[i]tolist[length-1]).Swap the smallest item found with the item at
list[i].Increment
i.Repeat steps 2-4 until the end of the list is reached.
Key Functions for Selection Sort Implementation
Defined in the
arrayListTypeclass:
template<class elemType>
class arrayListType {
public:
void selectionSort();
private:
void swap(int first, int second);
int minLocation(int first, int last);
};
minLocation Function
Returns the index of the smallest element within a subsection of the list:
template <class elemType>
int arrayListType<elemType>::minLocation(int first, int last) {
int minIndex = first;
for (int loc = first + 1; loc <= last; loc++) {
if (list[loc] < list[minIndex]) {
minIndex = loc;
}
}
return minIndex;
}
Swap Function
Swaps two elements in the list:
template <class elemType>
void arrayListType<elemType>::swap(int first, int second) {
elemType temp = list[first];
list[first] = list[second];
list[second] = temp;
}
Selection Sort Function
Implements the selection sort algorithm within the class: (4 min)
template <class elemType>
void arrayListType<elemType>::selectionSort() {
int minIndex;
for (int loc = 0; loc < length - 1; loc++) {
minIndex = minLocation(loc, length - 1);
swap(loc, minIndex);
}
}
Time Complexity of Selection Sort (4:20 min)
Selection sort has a time complexity characterized by:
O(n^2) for the key comparisons made by the algorithm.
The function swap and minLocation function will have specific assignment and comparison counts:
Number of item assignments in swap: 3(n-1).
Number of key comparisons in minLocation: O(n^2).
Insertion Sort (5:00 min)
The insertion sort algorithm improves upon selection sort's performance by maintaining a sorted order as elements are added to the final sorted part of the list.
Steps of the Insertion Sort Algorithm
Initialize
firstOutOfOrderto 1.For each
firstOutOfOrder, if the current element is less than the previous one, keep shifting elements to make space for the insertion of the out-of-order element.Repeat until the list is fully sorted, shifting each out-of-order element to its proper position.
Insertion Sort Code Example
template <class elemType>
void arrayListType<elemType>::insertionSort() {
int firstOutOfOrder, location;
elemType temp;
for (firstOutOfOrder = 1; firstOutOfOrder < length; firstOutOfOrder++) {
if (list[firstOutOfOrder] < list[firstOutOfOrder - 1]) {
temp = list[firstOutOfOrder];
location = firstOutOfOrder;
do {
list[location] = list[location - 1];
location--;
} while (location > 0 && list[location - 1] > temp);
list[location] = temp;
}
}
}
Demonstration Example
Using a sample list:
Initial list:
[13, 7, 15, 8, 12, 30, 3, 20]
First iterations of operations show how elements are moved to their proper places. Each shift operation ensures that a sorted portion of the list gradually grows and incorporates the elements in correct order.
Time Complexity of Insertion Sort (6:20)
Insertion sort's time complexity is also O(n^2) in the worst case, but it can perform in O(n) time for nearly sorted data, making it efficient in specific situations. (6:40)
Merge Sort (7:13)
Merge sort uses a divide-and-conquer strategy to sort a list.
Steps for Merge Sort
Partition the List: Split the list into two sublists until no further partitioning is possible.
Continue partitioning until each sublist contains one or zero items.
Merge the Sublists: Combine the sublists back into a single sorted list.
Compare elements and adjust references until all elements are sorted.
Basic Merge Sort Implementation in C++
template<class Type>
void unorderedLinkedList<Type>::mergeSort() {
recMergeSort(first);
if (first == NULL) last = NULL;
else {
last = first;
while (last->link != NULL) last = last->link;
}
}
Divide Functionality in Merge Sort
The divide function locates the central node using two pointers, effectively splitting the linked list into two halves for further processing.
Merge Functionality in Merge Sort (8:14 better explanation)
The merge function reconciles two pre-sorted lists back into a single ordered list, employing element comparisons to appropriately link nodes.
Time Complexity of Merge Sort (8:45)
Maximum number of comparisons made by mergesort: O(n log2 n)→(grows much slower than O(n) )
The function W(n) denotes the number of key comparisons, showing a worst-case scenario to sort L as W(n) = O(n log2 n).
Comparison of Sorting Algorithms
Insertion Sort vs Selection Sort: Analysis of average-case behavior indicates performance differences based on the specific conditions of the input data of length n.
Merge Sort vs Quick Sort: Comparison highlights:
Quick Sort averages to O(n log2 n) but has a worst-case of O(n^2).
Merge Sort consistently performs at O(n log2 n), owing to its stable partitioning strategy.
The method of partitioning the list varies significantly between both algorithms, influencing their performance and efficiency against different datasets.