Week 8 Tutorial — Sample Solutions

  1. In the notation below, the contents of the stack is indicated by << >>, with the top on the left.
    In other words: <<top, ... >>

    Initially:    << >>
    After push 1: <<1>>
    After push 5: <<5, 1>>
    After push 3: <<3, 5, 1>>
    After pop:    <<5, 1>>
    After push 4: <<4, 5, 1>>
    After push 2: <<2, 4, 5, 1>>
    After pop:    <<4, 5, 1>>
    After pop:    <<5, 1>>
    After pop:    <<1>>
    After pop:    << >>
    

  2. In the notation below, the contents of the queue is indicated by << >>, with the start on the left and the end on the right
    In other words: <<start, ..., end>>

    Initially:       << >>
    After enqueue 1: <<1>>
    After enqueue 5: <<1, 5>>
    After enqueue 3: <<1, 5, 3>>
    After dequeue:   <<5, 3>>
    After enqueue 4: <<5, 3, 4>>
    After enqueue 2: <<5, 3, 4, 2>>
    After dequeue:   <<3, 4, 2>>
    After dequeue:   <<4, 2>>
    After dequeue:   <<2>>
    After dequeue:   << >>
    

    1. The new node is being placed at the head of the list, but it will not work because the head is not being returned. The code should be:
      NodeT *insertHead(NodeT *head, int v) {
         // create new node with data
         NodeT *new = (NodeT *)malloc(sizeof(NodeT));
         assert (new != NULL);
         new->data = v;
         new->next = head;
         return new;
      }
      
      This is called head insertion.

    2. Insert a node at the end of a linked list (called tail insertion):
      NodeT *insertTail(NodeT *head, int v) {
         // create new node with data
         NodeT *new = (NodeT *)malloc(sizeof(NodeT));
         assert (new != NULL);
         new->data = v;
         new->next = NULL;
         if (head != NULL) {            // check if at least 1 node
            NodeT *cur;
            cur = head;                 // start at the head
            while (cur->next != NULL) { // this must be defined
               cur = cur->next;
            }
            cur->next = new;            // cur->next was NULL
         } else {
            head = new;
         }
         return head;
      }
      

  3. Variations of the 2 strategies are of course possible.

  4. An implementation of a duplicate checker:

    // assumes the linked list is sorted
    int hasDupList(NodeT *head) {          // 1 if dup found, otherwise 0
       int found = 0;
       if (head != NULL && head->next != NULL) { // need at least 2 nodes
          NodeT *cur;
          cur = head;
          while (cur->next != NULL && !found) {  // walk the list
             if (cur->data == cur->next->data) {
                found = 1;                       // we found a dup
             } else {
                cur = cur->next;
             }
          }
       }
       return found;
    }