L21 - operator= in Linked List and Recursion

#ece244

Recall from L19's linked list class definition:

#include 'Node.h'

class List {
	private:
		Node* head;
		int data;
	public:
		List() { head = NULL; } // default constructor; set head to NULL
		~List() { delete head; } // destructor; deallocate head node
		void insertData(int d); // insert data into the linked list
		bool dataExists(int d); // search list for data and return bool
		bool deleteData(int d);
		// delete data from list; returns bool for existence of data
		List (const List&); // copy constructor
		List& operator=(const List&); // operator= definition
}

operator= in a linked list

Recall from L14, the operator= operator sets the LHS values equal to the RHS values. However, normally this would just copy over pointers and not the values at the pointers, so modifying the values at those pointers would affect both RHS and LHS. So, we should define our own operator=. This is very similar to the copy constructor, but we also need to deallocate whatever is at the original linked list, instead of allocating an entirely new linked list. We must consider the following cases:

List& List::operator=(const List& rhs) {
	// 1. first, check for self-assignment between RHS and LHS
	if (&rhs == this) { // invokes &rhs.operator==(this)
		return *this;
	}
	
	// 2. free the old list, if there exist nodes in 'this' already
	if (head != NULL) {
		delete head; // recursively deletes each node in the linked list
		head = NULL;
	}
	
	// 3. copy the RHS list to the LHS
	// same as copy constructor code
	
	Node *p = original.head;
	Node *np = NULL;

	while (p != NULL) {
		Node *n = new Node(p->getData(), NULL);
		if (np == NULL) { // make the first node the head
			head = n;
		} else { // if np is already a non NULL node pointer
			np->setNext(n); // set the next of previous node to new node
		}
		p = p->getNext(); // shift p along original list
		np = n; // make np the current node
	}
	
	return *this;
}

Notes:

Tl;Dr: operator= copies an existing object into another existing object.

As opposed to a copy constructor, which copies an existing object into a newly-allocated object.


recursion

We learnt this before! In APS105! Recall:

The definition in C++, of course, is the exact same. Let's go through some examples together.


recursion example 1: find factorial

Let's write a function that finds the factorial of an integer. We did this in APS105 too!

Factorial of a number

The factorial of a number n is expressed as n!, and is equal to: $$n(n-1)(n-2)(n-3)\times\dots 2\times 1$$

We can implement this recursively by multiplying by n each time.

#include <iostream>
using namespace std;

int factorial(int n) {
	if (n > 1) {
		return factorial(n-1) * n;
	}
}

int main(void) {
	int n = 4;
	cout << "Factorial of " << n << " is " << factorial(n) << endl;
	return 0;
}