Had my first practice exam for COMP2521 this week!.

Sorted Array Validation

Task
Write a function that recursively checks if an array is sorted

Prototype
bool search_p (int xs[], int l, int r)
xs - array
l - left index
r - right index

Code

1
2
3
4
5
6
7
8
9
bool search_p (int xs[], int l, int r) {
    // exit-case: if the left and right indices cross
    if (l > r) return true;

    // check the indices
    if (xs[l] > xs[r]) return false;

    return search_p(xs, l+1, r);
}

Fibonacci Linked List

Uhm I lost 0.1 marks from this question…

Task
Write a function that generates a linked list of n Fibonacci numbers. This question had a quirk… fib(0) -> NULL, and fib(1) -> item(0)

Prototype
node *fibonacci(int n)

Code

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
typedef struct node *Node;
struct node {
    int item;
    Node next;
};

/*
 *  Function: new_node
 *  Creates a node with the item value `i`
 */
Node new_node(int i) {
    Node new = malloc(sizeof(*new));
    (*new) = (struct node) {
        .item = i,
        .next = NULL
    }
}

node *fibonacci(int n) {
    if (n == 0) return NULL;

    Node head = new_node(0);  // Set up the 1st element (0)
    if (n == 1) return head;  // And return if fibonacci(1)

    Node tail = new_node(1);  // Set up the 1st element (0)
    head->next = tail;
    if (n == 2) return head;  // And return if fibonacci(2)

    //

    // Variables to hold the last two values
    int prev1 = head->item; // 0
    int prev2 = tail->item; // 1

    for (int i = 3; i <= n; i++) {
        // Make a new node out of the sum of the last two values
        int nextVal = prev1 + prev2;
        Node n = new_node(nextVal);
        
        // Link and reassign the tail
        tail->next = n;
        tail = n;

        // Update the last two values
        prev1 = prev2;
        prev2 = n->item;
    }

    return head;
}

DList Relink

Task
Given two doubly linked lists x and y, write a function that moves all elements from y to x

Prototype
void list_relink(DList x, DList y)

Code

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
typedef struct dlist *DList;
typedef struct dnode *DNode;

struct dlist {
    int size;
    DNode head;
    DNode tail;
};


struct dnode {
    int item;
    DNode next;
    DNode tail;
};

//

void list_relink(DList x, DList y) {
    // If y is empty then we don't need to do anything
    if (y->size == 0) return;

    if (x->size == 0) {
        // If x is empty, then just move the head from y
        x->head = y->head;
    } else {
        x->tail->next = y->head;
        y->head->prev = x->tail;
    }
    
    // Update the new meta for x
    x->tail = y->tail;
    x->size += y->size;

    // Unlink y
    y->head = NULL;
    y->tail = NULL;   
    y->size = 0;
}

BST Validation

Task
Given a binary search tree, write a function to check that the search property is held true.

Prototype
bool bst_valid(node *tree)

Code

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
typedef struct node *Node;
typedef struct node {
    int item;
    Node left;
    Node right;
}

bool bst_valid(Node tree) {
    if (tree == NULL) return true;

    // if the left subtree exists, ensure that its item is less than the parent
    if (tree->left) {
        if (!(tree->left->item < tree->item)) return false;
    }

    // if the right subtree exists, ensure that its item is more than the parent
    if (tree->right) {
        if (!(tree->right->item > tree->item)) return false;
    }

    // check down the tree
    return bst_valid(tree->left) && bst_valid(tree->right);
}

BST Prune

I lost 3 marks from this question, not sure where since they don’t release the solutions

Task
Write a function that drops the nodes past a given depth

Prototype
void btree_prune(Node tree, int depth)

Code

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
typedef struct node *Node;
typedef struct node {
    int item;
    Node left;
    Node right;
}

/*
 * Function: btree_drop
 * Recursively release all nodes
 */
void btree_drop(Node tree) {
    if (!tree) return;
    btree_drop(tree->left);
    btree_drop(tree->right;
    free(tree);
}

//
Node btree_prune(Node tree, int depth) {
    if (depth == 0) {
        btree_drop(tree->left);
        btree_drop(tree->right);
        tree->left = tree->right = NULL;
        return NULL;
    } else {
        tree->left = btree_prune(tree->left, depth-1);
        tree->right = btree_prune(tree->right, depth-1);
    }
    return tree;
}

Explanation In order to drop elements only greater than (or equal) to a given depth, I would need to implement some sort of counter.
However, I could not modify the btree_prune function prototype. I could have written a helper function, and turn btree_prune into a wrapper function - but another was was to use the depth parameter!

By decreasing depth, we are effectively saying n more levels to go until we start dropping everything”.