2026-01-05
By the end of this lecture, you should be able to:
makefile.Definition
A data structure is a method of storing and organizing data to enable efficient access, manipulation, and modification.
Examples:
Choosing suitable data structures is a key aspect of designing efficient and scalable algorithms.
Definition
An algorithm is a well-defined computational procedure that accepts input values and produces output values in a finite amount of time.
Examples:
Studying data structures and algorithms helps you design usable software. In this course, we will repeatedly ask these practical questions about computational procedures:
Is it correct?
Does it always terminate?
Given a particular data structure as input, how much
An array is the simplest data structure, designed to store a collection of elements.
Suppose the array begins at memory address \(a\), and each element requires \(b\) bytes of memory:
The “\(-1\)” appears because the byte range is inclusive.
We adopt the RAM model: the time required to access an array element by index is independent of the index.
vectorIn C++, the Standard Template Library provides std::vector, a dynamic array type.
Key properties:
v[i].push_back(x) appends an element.pop_back() removes the last element.v.size().A vector is the default choice when you need an “array whose size can change.”
We can verify contiguity by printing the addresses of the elements:
v[i] and v[i+1] differ by the element size.v is a vector<int> and sizeof(int) = 4, then the addresses should increase by 4 bytes.You can download a demo program by unzipping this ZIP file, where we print:
v[i]&v[i]The purpose of this program is to observe that the addresses form a regular pattern: each element starts immediately after the previous one. The content, build process, and output from the program are shown below.
vectorIn the code below:
&v[i] to const void* so that streaming it to std::cout prints the pointer value (the address) rather than treating it as character data.std::ptrdiff_t is the signed integer type used to store the result of subtracting two pointers (i.e., the offset between two addresses):#include <cstddef>
#include <iostream>
#include <vector>
int main() {
const std::vector<int> v{42, -17, 9382, 0, 30};
std::cout << "sizeof(int) = " << sizeof(int) << " bytes\n";
for (std::size_t i = 0; i < v.size(); ++i) {
std::cout << "v[" << i << "] is at " << static_cast<const void *>(&v[i]);
if (i > 0) {
const std::ptrdiff_t d = &v[i] - &v[i - 1];
std::cout << " (diff=" << d * sizeof(int) << " bytes)";
}
std::cout << "\n";
}
}Navigate to the directory containing the demo program and enter the following commands in a Terminal:
All address differences in the output shown on the previous slide are equal to sizeof(int). Consequently, the memory addresses for the elements of v are contiguous.
Task: Replace int with other data types and convince yourself that elements of non-integer vectors also occupy contiguous blocks of memory.
Sorting rearranges the elements of an array into nondecreasing order. The elements to be sorted are referred to as keys. In this section, we study the classic insertion sort algorithm.
Sorting Problem
Input: Sequence of numbers \(\langle a_1, a_2, \ldots, a_n\rangle\)
Output: Permutation \(\langle a_1', a_2', \ldots, a_n'\rangle\) such that \(a_1' \leq a_2' \leq \ldots \leq a_n'.\)
Example
Input: \(\langle 31, 41, 59, 26, 41, 58\rangle\)
Output: \(\langle 26, 31, 41, 41, 58, 59\rangle\)
Imagine sorting a deck of cards. At all times, the cards in your hands remain sorted, and they are exactly the cards you have picked up so far.
The next slide formalizes this idea.
Start with empty hands and a pile of cards on the table.
Pick one card, say \(X\), from the pile.
Insert \(X\) into the correct position among the sorted cards in your hands:
Repeat steps 2–3 until all cards are in your hands.
Here is a video tutorial on insertion sort. You can use YouTube’s playback features to view closed captions.
Note that the video uses 1-based indexing for arrays—as does our textbook (Cormen et al., 2022)—whereas C++ uses 0-based indexing.
Open the app: https://apps.michael-gastner.com/insertion-sort/.
Use the buttons to watch the array being sorted.
active_key (shown in light blue): the value currently being inserted into the sorted left subarrayi: number of keys sorted so far (sorted left subarray is a[0 .. i - 1]; 0-based indexing)h: index of the hole—the empty slot left behind after taking out active_key; it moves left as larger elements are shifted right, and active_key is eventually placed at a[h]Below the Array State panel, the app displays pseudocode with these features:
To the right of the pseudocode, the app displays a Statistics panel that counts work done as you step through the algorithm:
We will connect these counts to running time in the next lecture.

During one outer iteration (i.e., one insertion), insertion sort performed 7 comparisons and 3 shifts.
Recall: the while condition is h > 0 and a[h - 1] > active_key, and comparisons are counted with short-circuit evaluation. What must be true?
active_key was equal to the index after the insertion.active_key was inserted at index 0.active_key was inserted at index 4.Definition
A loop invariant is a property \(\boldsymbol{I}\) that we require to hold at the loop head (i.e., right before the loop condition is checked). It may be false inside the loop body.
A well-chosen loop invariant is a proof tool. Its value at termination can reveal whether an algorithm is correct for any valid input.
Loop invariant of insertion sort: At the start of each for loop iteration i in line 2 of the pseudocode in Figure 1, the subarray a[0 .. i - 1] is sorted.
To prove correctness, we must show:
Goal: When the algorithm finishes, a[0 .. n_keys - 1] is sorted.
Outer-loop invariant (at the loop head): At the start of each outer iteration with index i (1 ≤ i ≤ n_keys - 1), the subarray a[0 .. i - 1] is sorted.
i = 1, so a[0 .. 0] has one element and is trivially sorted.a[0 .. i - 1] is sorted, the loop body inserts active_key = a[i] into its correct position because of the while loop condition a[h - 1] > active_key on line 5 of Figure 1. Thus, a[0 .. i] sorted.i = 1 .. n_keys - 1, so it is guaranteed to terminate. In the while loop, h decreases by 1 on each shift and is bounded below by 0, so the while loop must also terminate.a[0 .. n_keys - 1] is sorted.Let us move from theory to practice and implement insertion sort in C++. Download this ZIP file, which splits the project into these files, following common C++ practices:
.h) contain function declarations..cpp) contain function definitions (the function bodies).For example, insertion_sort.h declares insertionSort(...), while insertion_sort.cpp defines it.
insertion_sort.hThe preprocessor directives at the top and bottom implement an include guard, which prevents multiple inclusions of the same header file.
insertion_sort.cppIn the labs, you will write C++ code and submit your programs to Gradescope for autograding. Gradescope requires a makefile so that the autograder can compile your submission consistently.
We will always provide the required makefile, so you do not need to write one yourself. However, you do need to know how to use a makefile to compile and run your C++ programs locally before submitting them to Gradescope.
The following slides explain how to accomplish this task.
Place the makefile alongside all required .cpp and .h files in the same directory. Then compile the code as follows:
make clean to remove build artifacts from previous compilations. This step avoids confusing results if you have an old executable or stale object files.make to build the program.If compilation succeeds, you will obtain an executable (as specified by TARGET in the makefile). In this example, the executable is named insertion_sort.
The ZIP file you downloaded contains sample input files named test_0.txt:
Then run:
The program prints the sorted integers separated by commas.
For lab assignments, you will submit your C++ code to Gradescope, which will automatically test your code. Let’s use insertion_sort.cpp as an example.
Navigate to the assignment “Week 01 Lecture: Gradescope Demo—Insertion Sort” in the xSITe Dropbox for our course. This assignment is for demonstration purposes only and won’t be graded. However, please read the assignment instructions carefully because the lab assignments will be similar.
Follow the link to Gradescope and upload the file insertion_sort.cpp. Once submitted, the Gradescope autograder will run the tests and provide feedback on your code.
makefile to compile and run it. ↪In the lab later this week, you will study an alternative sorting algorithm called merge sort. Here is a preview:
Week 01: Foundations (Lecture)