CS/COE 447: Spring 2010 Programming Assignment 3 YOUR NAME: Your solution to this assignment must be your own individual work. Programming assignments should be uploaded to coursed at http://courseweb.pitt.edu. Create a zip file with your three programs, and call it "PA3" followed by your name. The individual files should be called, e.g., "PA3part1" followed by your name. In this assignment, you will become familiar with the implementation of linked lists and dynamic memory allocation. *******Part 1 [30 points]: The following is a singly-linked list stored in memory. ``list'' points to the front of it. Each node in the list uses two words, one for the data value stored in that node and one for a pointer to the next node in the list. A next pointer of 0 indicates the end of the list. .data .word #data,next 3,0x10010018, 4,0x10010020, 2,0x10010028, 6,0x10010008, -1,0x10010010, -5,0x0 list: 0x10010000 In order to access the list, a pointer to the first node is needed. ``list'' above is a pointer to the first node of the list, which is stored at address 0x10010000. If the list was empty, ``list'' would contain 0. The data of the first node is 3, and the next pointer of that node is 0x10010018. Thus, the second node of the list is stored at 0x10010018. The last node of the list is the one whose data is -5, since its next pointer is 0. If you assemble the above code in Mars, you will be able to see which nodes are stored where (and draw the list on paper). Because each node contains a pointer to the next one, the nodes of a list do NOT need to be stored sequentially in memory (as array elements need to be). In the first part of this assigment, your task is to write a procedure named "print_and_sum_list" which, given a pointer to the first node of a single-linked list will print the data values in each of the nodes and the sum of those values. The pointer to the first node of the list should be passed to "print_and_sum_list" in $a0. ## # Procedure: print_and_sum_list(list) # # Sum and print the elements of a linked list in the order the list is # traversed and print the sum at the end. # A plus sign ('+') must be printed before a non-negative data value, # an equals sign ('=') must be printed before the sum and # a newline ('\n') must be printed at the end. # # Arguments: # list ($a0) - address of the first node of a singly-linked list of 1-word # integers. # Your program should create a list in the .data section similar to the one shown above and call procedure "print_and_sum_list" with the address of the first node. For the sample list above, the program's output should be: +3+6+4-1+2-5=9 *******Part 2 [40 points]: Linked lists are often used when the number of elements in a collection is unknown at coding time. Thus, the nodes of a linked list are often allocated at runtime in a memory region known as the heap. In MIPS, the heap starts after the statically allocated data (i.e., the .data section in an assembly program) and grows towards the top of the runtime stack. However, there is no "heap register" that points to the top of the heap, but the operating system keeps track of the size of the heap for a particular program. Syscall 9 (sbrk) in MARS can be used to increase or decrease the size of the heap by a number of bytes. Unlike the runtime stack, heap-allocated memory is not lost when returning from a function. High-level language programs typically use a library routine or a keyword for heap-memory allocation (e.g., "malloc" in C, "new" in Java). Deallocating heap-memory is often complex because memory chunks are not released in the same (or opposite) order they were allocated. So the programmer must explicitly deallocate memory (e.g., "free" in C) or rely on assistance from a complex runtime system (e.g., garbage-collection in the Java Virtual Machine). In this part of the assignment, you will only insert values into a sorted list (not delete them as well). To insert a value into a sorted list, first create a new node, with that value as its data. Memory for the node must be allocated using syscall 9 (sbrk). Starting at the beginning of the list, traverse it until you find where the new node should go (so that the list will still be sorted after the insertion). Finally, splice the new node into the list, so that the node before it points to *it*, and *it* points to the node following it. For example, to insert a 5 into the following list: list --> 1 --> 3 --> 7 --> 9 You need to do this: list --> 1 --> 3 --> 5 --> 7 --> 9 That is, you need to make 3 point to the new node, and the new node point to 7. Two special cases need to be handled: inserting a node into an empty list, and inserting a node that belongs at the end of the list (e.g., inserting 11 into the example above). Also notice that if the data value is smaller than all the values currently in the list, the new node will become the new first node and "list" must be updated. In this part of the assignment you must write the following subroutines: ## # Function: create_node(value) # # Allocate memory using syscall 9 (sbrk) for a new linked list node and # and initialize its data field to value. # # Argument: # value ($a0) - an integer # Returns: # the address of the new node (in $v0) # ## # Function: insert(list,value) # # Insert a value into its proper place in the linked list so that the list # remains sorted. # # Arguments: # list ($a0) - address of the first node of a singly-linked list of 1-word # integers whose elements are sorted in increasing order. # value($a1) - an integer to be inserted into the list # # Returns: # address of the first node of the list (in $v0) # # Algorithm: # // Make sure you understand this algorithm before implementing it in MIPS # // p->data refers to the data field of the node pointed to by p # // p->next refers to the next field of the node pointed to by p # newPtr = create_node(value) # previousPtr = 0 # currentPtr = list # while (currentPtr != 0 && value > currentPtr->data) { # previousPtr = currentPtr; # currentPtr = currentPtr->next; # } # if (previousPtr == 0) { # newPtr->next = list # returnValue = newPtr; # } else { # previousPtr->next = newPtr; # newPtr->next = currentPtr; # returnValue = list # } # return returnValue # The subroutines should follow the calling conventions for registers as listed on the green card. To test your subroutines, you must write a main program that calls them. Call "insert" five times, once with each of the following values: -2, 8, 0xd, 0, -5. Also, copy "print_and_sum_list" from Part 1 and call it to print the list before the first call to "insert" and then after each call to "insert". *******Part 3 [30 points]: In this part of the assignment you must write a function to merge two sorted lists into a single list. Your function does not need to allocate new nodes, but rather modify the next pointer fields in the nodes of the input lists to correctly form the merged list. ## # Function: merge(list1,list2) # Merges two sorted linked lists. # Arguments: # list1 ($a0) - address of the first node of a sorted list # list2 ($a1) - address of the first node of another sorted list # Returns: # address of the first node of the merged list (in $a0) # # Algorithm: # // Make sure you understand this algorithm before implementing it in MIPS # list3 = 0 # ptr1 = list1 # ptr2 = list2 # ptr3 = list3 # while (ptr1 != 0 && ptr2 != 0) { # if (ptr1->data < ptr2->data) { # ptr3_next = ptr1 # ptr1 = ptr1->next; # } else { # ptr3_next = ptr2 # ptr2 = ptr2->next; # } # if (ptr3 != 0) { # ptr3->next = ptr3_next; # } else { # list3 = ptr3_next # } # ptr3 = ptr3_next; # } # if (ptr1 != 0) { # ptr3_next = ptr1; # } # if (ptr2 != 0) { # ptr3_next = ptr2; # } # if (ptr3 != 0) # ptr3->next = ptr3_next; # else # list3 = ptr3_next; # returnValue = list3 # To test your function, write a main program that uses "insert" from Part 2 to build the following lists: list1 --> -3 --> 1 --> 5 list2 --> -4 --> -2 --> 3 --> 8 And then calls "merge" to merge them. Call "print_and_sum_list" from Part 1 after creating list1 and list2 and after calling merge.