Tutorial Solutions Week 1

A file with all the code solutions for exercise 1 and 3 and its helper functions can be found here: Lists_sol.c

A file with all the code solutions for exercise 2 and its helper functions can be found here: ListsAlternate_sol.c

Exercise 1 - Linked Lists

  1. Consider the material on linked lists that we discussed in the lecture with the following definition (Item is a char now):

    typedef char Item;
    
    typedef struct node *link;
    
    struct node {
      Item item;
      link next;
    };
    

    Write the following functions:

  2. Assume we have a function printList which, given a list of characters, prints each character, and a function `cstrToList` which converts a regular C string (i.e., `\0` terminated array of characters) into a list of characters. What is the output of the following program? (See implementation of reverse in Exercise 2.)

    int main (int argc, const char * argv[]) {
      link ls = cstrToList ("hello world!");
      link ls2 = duplicate(ls);
      printList (ls);
      printList (reverse (ls));
      printList (ls);
      printList (ls2);
      return 0;
    }
    

  3. List elements: hello world!
    List elements: hello world!
    List elements: !dlrow olleh
    List elements: h
    List elements: hello world!
    

    reverse returns a pointer to the beginning of the reversed list, so when we print it out using printList(reverse (ls)); we get the list printed in reverse as we would expect. However, we did not assign the beginning of the reversed list back to our ls variable, so it is still pointing to the original head of the list which has the item 'h' in it. This node has now been modified to point to NULL during the reverse function, so printing out the ls list now results in simply an 'h' being printed out. If we wanted our ls variable to now contain the list in reverse we would have had to have used the return value as such ls = reverse(ls) . The duplicate list, ls2, as we would hope, has not been changed by calling the reverse function, as it has its own copies of all the nodes.

Exercise 2 - Linked Lists, an alternative implementation

Exercise 3 - Double linked lists

In the lecture, we briefly discussed doubly linked lists.

typedef char Item;

typedef struct dnode *dlink;

struct dnode {
    Item  item;
    dlink next;
    dlink prev;
};

Write a function

dlink append (dlink list1, dlink2 list2)
dlink append(dlink list1, dlink list2){
    dlink curr;
    dlink newList;
    if(list1 != NULL){
        for(curr = list1; curr->next != NULL; curr = curr->next){
        }
        curr->next = list2;
        if(list2 != NULL){
            list2->prev = curr;
        }
        newList = list1;
    } else {
        newList = list2;
    }
    return newList;      
}

which attaches the list list2 at the end of list1 and returns the resulting list.

Is it necessary to return the resulting list, or would the following interface work (as list1 is altered)

void append (dlink list1, dlink list2)

This will not work. You need to return the resulting list incase the first list is NULL