CS 202 (FALL 2019) - EXAM 3 NAME: Points: 31.5 points total 0 C Programming (assessment), 3 pts each ======================================== - Give C code for each of the following. Note - you DON'T need to give a complete program (no #include, etc.), and there WILL be partial credit (if merited). 1. Read an integer n from the user, and print the following for each i between 1 and n - list of factors of i. For n=6 the output would be - 1 - 1, 2 - 1, 2, 3 - 1, 3, 4 - 1, 2, 4, 5 - 1, 5, 6 - 1, 2, 3, 6, int n; scanf("%d", &n); for(int i=1; i <= n; i++) { printf("%d Ð ", i); for(int j=1; j <= n; j++) if (i % j == 0) printf("%d, ", j); printf("\n"); } 2. Read from stdin until EOF and count how many upper-case and lower-case alpha characters there are. Print the totals after done reading input. You can assume cypte.h has been #include'ed. int ch; int upper = 0, lower = 0; while ((ch = getchar()) != EOF) { if (isupper(ch)) upper++; if (islower(ch)) lower++; } printf("upper %d, lower %d\n", upper, lower); 3. Read an integer and print out what the integer is as a sum of powers of 2. You can assume the integer is positive. If 42 were input the output would be 42 = 2 + 8 + 32 int n; scanf("%d", &n); printf("%d = ", n); int val = 1; while (n > 0) { if (n % 2 == 0) { printf("%d", val); if (n > 1) printf(" + "); } n /= 2; } printf("\n"); 1 Functions Every Citizen Should Know, 1 pt each ================================================ - Answer the following questions about standard C functions: 1. What is the meaning of the first parameter to realloc? pointer to memory that is currently allocated 2. What is the type of the first parameter to scanf? C string, aka char *, aka string constant 3. Explain the difference between fputc and putchar. fputc puts a character to a given FILE *, while putchar always puts to stdout 4. What is the meaning of the second parameter to strcat? pointer to string to be appended to the first string 5. Explain the meaning of the return value of strcmp. 0 if strings are identical, - if first string is smaller, + if first string is larger. 2 Asymptotic Complexity, 1 pt each ================================== - For each of the following pseudocodes, give the worst case run time in Big O notation. Note: Show your work / explain how you arrived to this conclusion. PAY ATTENTION TO THE DETAILS of each program! 1. Let a, b, c be arrays of size n. for(int i=0; i < n; i++) a[i] = i; for(int j=0; j < n; j++) b[i] = a[i]*a[i]; for(int k=0; k < n; k++) c[i] = b[i] - a[i]; int sum = 0; for(int i=0; i < n; i++) { for(int j=0; j < n; j++) { sum += c[i] + a[i] - b[i]; } } Initialization loops are each O(n), adding them up is O(n). Nested loops are O(n**2). Overall, itÕs O(n**2). 2. Let a, b, c be arrays of size n. for(int i=0; i < n; i++) { for(int j=0; j < n; j++) { for(int k=0; k < n; k++) { printf("%d\n", a[i] * b[j] * c[k]); k = n-2; } j = n-2; } } The code actually is an infinite loop because the inner loop sets k=n-2 each time, k++ gives k=n-1, and k will never be >= n. I had meant to have something like: if (k < n-2) k=n-2; And in that case then answer would be the following. There are three nested loops, so it could end up being O(n**3). But the two inner loops are short-cutted by setting k=n-2 and j=n-2, meaning they really don't incur a factor of n in the running time. So, O(n). 3. Let root be the root of a binary search tree that contains n nodes. void free_tree(bst_t *curr) { if (curr == NULL) return; free_tree(curr->left); free_tree(curr->right); free(curr); } free_tree(root); One recursive call for each node in the tree, and each recursive call has a constant amount of work (calling free, calling left and right). n nodes total, with O(1) work at each node, so O(n) total. 4. (3 points) Put the following in big-O order. For two functions in your order, put = between them if they are Theta of each other, and put < if they are not. For example, for the functions f(n) = log(n), g(n) = 2*n, h(n) = n/2 - 100, the correct answer would be f(n) < g(n) = h(n). Note that ** is used for exponentiation. t1(n) = sqrt(n) t2(n) = log(n) t3(n) = n**n t4(n) = n**(log n) t5(n) = 2**n t6(n) = n**4 - 100n t7(n) = 10n + log(n) + 1000 t8(n) = n log(n) + 50n t9(n) = n t2(n) < t1(n) < t9(n) = t7(n) < t8(n) < t6(n) < t4(n) < t5(n) < t3(n) 3 Hash Tables, 1.5 pts each =========================== 1. Hash function - what is the purpose and give an example for integers (don't need to give code, can use math notation or however you want to specify) Map a key to an index into the hash table. Example: h(x) = x % TABLE_SIZE 2. Insert - give pseudocode for the insert function for a hash table of size T that uses buckets for collisions. i = h(key, T) insert (key, data) into bucket i of the table. 3. Running time - what is the best, worst, and expected running time for insert? And for lookup? Assume a hash table that uses buckets for collisions. Insert: constant time Ð because insert into a linked list is constant time. Lookup: constant best and average case (assuming parameters are chosen well and a good hash function), linear worst-case. 4 Linked Lists, 1.5 pts each ============================ 1. Complete the code for linked list lookup. typedef struct NODE { int data; struct NODE *prev, *next; } node_t; node_t *lookup(node_t *head, int value) { for(node_t *p = head; p != NULL; p = p->next) if (p->data == value) return p; return NULL; } 2. Draw a picture of what happens for the insert operation for a doubly linked list. Assume the data are integers and the new value to insert is 37. Write code for insert assuming node_t as given above, a non-NULL head pointer, and a new node p has already been created with data 37. [NULL | 37 | /next/] <-> [/prev/ | value | /next/] <-> [/prev/ | value2 | /next/] <-> head->prev = p; p->prev = NULL; p->next = head; head = p; 5 Binary search / AVL Trees, 1 pt each ====================================== 1. Draw what an AVL tree would look like if the following items are inserted in this order: 33, 45, 15, 50, 40 33 15 45 40 50 2. Choose one more number to insert that would cause a need for rebalancing. Draw the tree before rebalancing and after rebalancing. 60 33 45 15 45 33 50 40 50 15 40 60 60 6 Arrays, 1 pt each =================== 1. Write code for inserting to an unsorted array. You can assume numItems < MAX_ITEMS. int numItems; int data[MAX_ITEMS]; void insert(int value, int array[], int *numItems) { data[*numItems] = value; (*numItems)++; } 2. Deleting from a sorted array - basic idea and running time Ð Remove item to be deleted, shift everything else over to fill in the gap. Running time Ð O(n).