CSCI 161: Spring 2026 Final Exam (Prof. D. Wessels: Sections N01/N02)
- Make sure your name is clearly written on the exam
- Answer directly on the exam, extra paper and scrap paper is available if needed.
- You have 3 hours to complete the exam
- The exam is closed book, closed notes, no electronics are permitted,
but you are permitted one double-sided 8.5"x11" reference sheet ("cheat sheet").
- There are 8 questions worth 10 marks each,
for a total of 80 marks: attempt all questions.
- All VIU official rules for writing exams in the gym apply.
Question 1: Definitions and explanations [10]
In your own words, explain the meaning of the following terms in the context of our course:
- dynamic data types
- abstract data types
- inheritance
Question 2: Memory allocation/deallocation [10]
The code segment below contains examples of
- a memory leak
- a dangling pointer
- use of a wild pointer
- use of a null pointer likely to cause a run-time crash
For each of the four items described, clearly identify if and where in the code the problem originates
and outline a simple fix that maintains the desired code functionality. (Hint: three of the
four problems exist in the code.)
// assumes string and iostream are included, std namespace is in use
struct listnode {
int data;
listnode* next;
listnode* prev;
};
int main()
{
listnode* front;
listnode* back;
string entry = "";
listnode* tmp = nullptr;
back = nullptr;
do {
cout << "Enter numbers to insert them into the list, or" << endl;
cout << "P to print the list, R to remove a number, Q to quit" << endl;
int i;
cin >> i;
if (cin.fail()) {
// not an integer, read as a command string
cin.clear();
cin >> entry;
if ((entry == "P") || (entry == "p")) { // it was a print command
tmp = front;
cout << "list contents:";
while (tmp) {
cout << " " << tmp->data;
tmp = tmp->next;
}
cout << endl;
} else if ((entry == "R") || (entry == "r")) { // it was a remove command
if (front) {
front = front->next;
if (front) {
delete front->prev;
front->prev = nullptr;
} else back = nullptr;
}
}
} else { // insert the number in a new node at the back of the list
tmp = new listnode;
tmp->data = i;
tmp->next = nullptr;
tmp->prev = back;
if (front == nullptr) front = tmp;
else back->next = tmp;
back = tmp;
}
} while ((entry != "Q") && (entry != "q"));
while (front) { // deallocate all remaining listnodes
front = front->next;
if (front) delete front->prev;
else delete back;
}
}
Question 3: Linked lists [10]
Given the definition of a linked list class below, write the code for the
insert and remove methods.
// linked list of nodes, each with a number and text string in their data
// assumes iostream and string are #included and std namespace is in use
class LList {
protected:
struct lnode {
double num;
string text;
lnode* next;
};
lnode* front;
public:
LList(); // initialize an empty list
~LList(); // deletes each node in the list
void print(); // prints all nodes in the list
// inserts new node at front of list
void insert(double d, string s);
// removes and deletes node from front of list
// (no effect if list is already empty)
void remove();
};
Question 4: Mergesort [10]
In your own words, describe how a recursive mergesort works, illustrating your description by
showing how it sorts the following sequence (into ascending numeric order):
23 100 4 510 678 99 44 12
Question 5: Binary search trees I [10]
Suppose we have code that builds a valid binary search tree of numbers (using our usual approach of smaller
values in left subtrees, other values in right subtrees) and is given values to insert
in the following sequence:
19 30 77 80 14 6 3 18 74 78 74
(i) Sketch the binary search tree that would result
(ii) Show the order the tree contents would be printed in if printing used
an inorder traversal.
Question 6: Binary search trees II [10]
Given the definition of a binary search tree class below, and assuming the tree nodes are
organized based on their num fields (again, smaller in left subtrees):
same rules as described in question 5:
(i) Provide a recursive implementation of the protected print method.
(ii) Provide a loop-based implementation of the public lookup method.
// assumes iostream and string are #included and std namespace is in use
class bstree {
protected:
struct tnode {
float num;
string str;
tnode* left;
tnode* right;
};
tnode* root;
void print(tnode* t); // print all nodes of subtree t in sorted order
void deallocate(tnode* &t); // deallocate all nodes in subtree t
tnode* create(float n, string s); // allocate and return a new tnode with the given field values
public:
bstree(); // initialize empty tree
~bstree(); // deallocate the tree content
string lookup(float n); // find the node with num field n and return its str field, "" if not found
void print(); // print whole tree's data in sorted (by num) order
void insert(float n, string s);
};
Question 7: Inheritance [10]
For the trio of classes defined further below, answer the following two questions:
(i) Describe the meaning/purpose of the public/protected/private
sections of the parent class.
(ii) Describe the meaning/purpose of the 'protected parent' portion
of the child class definition, and how that impacts what is accessible in the grandchild class.
Be sure to list which parent/child sections the grandchild methods can access directly
and which they cannot.
class parent {
private:
// ... parent private fields and methods
protected:
// ... parent protected fields and methods
public:
// ... parent public fields and methods
};
class child: protected parent {
private:
// ... child private fields and methods
protected:
// ... child protected fields and methods
public:
// ... child public fields and methods
};
class grandchild: public child {
private:
// ... grandchild private fields and methods
protected:
// ... grandchild protected fields and methods
public:
// ... grandchild public fields and methods
};
Question 8: Overloading and overriding [10]
(i) In your own words, describe the special meaning and purpose of "this" and "*this" in C++ classes.
(ii) For the text class defined below, provide
an implementation of the overloaded = operator
// class to represent a dynamically-allocated char array,
// assumes iostream and cstring libraries are #included
class text {
protected:
int size;
char *content;
public:
text(const char* str = "");
~text();
text operator=(const text &rhs);
void print();
};
// sample main using the text class methods
int main() {
text s("hello world");
s.print();
text t = s;
t.print();
}
// implementation of text class methods
text::text(const char* str) {
size = strlen(str);
content = new char(size);
strcpy(content, str);
}
text::~text() {
if (content) {
delete content;
}
}
void text::print() {
std::cout << content << std::endl;
}
text text::operator=(const text &rhs)
{
// implementation to be completed by student