Professional Documents
Culture Documents
Hong Kong University of Science and Technology COMP104: Programming Fundamentals and Methodology
Hong Kong University of Science and Technology COMP104: Programming Fundamentals and Methodology
Fall 2004, Lecture Section 1, 2, 3 Final Examination Friday, Dec.17, 2004 08:30 11:30AM Student Name: Student ID: Instructions: This is a closed-book, closed-notes examination, calculator is also not allowed. Check that you have all 21 pages (including this cover page). Write your name, student ID, lecture section, lab section and TA name on this page. Please circle your answer. 5. Answer all questions in the space provided. Rough work should be done on the back pages.
1. 2. 3. 4.
key
Score
Simple Linked List Algorithms on Linked List Doubly Linked List Classes Dynamic Classes/ADT
Answer (1 mark): 2 + 3 != 5
c) Complete the following program to print the users input word in reverse order and check if it is a palindrome. A word is a palindrome if its reversion is the same as itself. For example, the output of the program should look like this: Enter a word to reverse: canoe Your word spelled backwards is: eonac It is not a palindrome. Or Enter a word to reverse: kayak Your word spelled backwards is: kayak It is a palindrome. Also, it should be case sensitive, i.e., kayak is a palindrome, but Kayak is not. You can use predefined C++ string functions such as xxx.length() (this function returns the number of characters of the given string xxx). (7 marks)
void main(){ string inword, outword; bool isPalindrome; // Get user input cout << "Enter a word to reverse: "; cin >> inword; // copy user input into outword, this will make sure // outword is long enough to contain inword outword = inword; // START YOUR CODE HERE ----->
// <---END YOUR CODE HERE // Output the reversed word and whether it's a palindrome cout << "Your word spelled backward is: " << outword << endl; if(isPalindrome) cout << "It is a palindrome" << endl; else cout << "It is not a palindrome" << endl; }
// 2 marks
3
outword[inword.length() - i - 1] = inword[i]; // 3 marks if(outword == inword) // 2 mark isPalindrome = true; else isPalindrome = false;
// <---}
Answer (5 marks): int n1, n2, n3; ifstream fin; fin.open(test.dat); // 1 mark // 1mark
// 1 mark
// 1 mark // 1 mark
The following function is supposed to delete multiple elements from an unsorted simple linked list which contains only positive integers. Given a key element k(a positive integer), the function searches and deletes all its multiples that are greater than itself. (i.e. nk, n>=2). The input parameter Head points to the first element of the linked list and delkey is the key element whose multiples are to be deleted. There are FIVE mistakes in the following implementation. Please identify and fix them all(you may have to add lines if needed).
1 void delMultiple (NodePtr Head, int delKey){ 2 NodePtr prev, cur = Head; 3 while(cur!=NULL){ 4 if(cur->data > delKey && cur->data % delKey == 0){ 5 if(cur!=Head) 6 Head = Head->next; 7 else 8 prev->next = cur; 9 NodePtr tmp = cur; 10 11 delete tmp; 12 } 13 else{ 14 15 cur = cur->next; 16 } 17 } // end of while 18 }
Answer(10 marks, 2 each): (-2 for each additional mistake) (1) (2) (3) (4) (5) line line line line line 1: should be pass by refernece 5: change to if(cur==Head) 8: change to prev->next = cur-> next 10: add cur = cur->next 14: add prev = cur
The following code segment is supposed to return the union of two simple linked lists. Assume the two functions, searchNode() and insertNode(), work properly, identify errors in the code and fix them.
1. void UnionLists(NodePtr Head1, NodePtr Head2){ 2. NodePtr Union, Cur; 3. Union = Head1; 4. Cur = Head2; 5. while(Cur != NULL){ 6. if(searchNode(Union, Cur->data)) 7. insertNode(Union, Cur->data); 8. Cur = Cur->next; 9. } 10. return Head2; 11. }
Answer(7 marks): a) Line 1: void should be NodePtr // 1 mark b) Line 6 should be: if(searchNode(Union, Cur->data)==NULL) // 2 marks c) Line 10: Head2 should be Union (-1 or more for adding other errors) // 2 marks
Write a function, findTotal(), which takes a simple linked list and returns the sum of all linked-list data. (7 marks)
Answer(7 marks): int findTotal(MylistPtr head){ int total = 0; while(head!=NULL){ total += head->data; head = head->next; } return total; } (-1 or more for adding other errors) // // // // // 1 1 1 2 1 mark mark mark marks mark
//1 mark
10
a) Write a print function for a doubly linked list with dummy head node such that all the elements are printed out in the REVERSE order. For example, your function should print out 30 20 10 for the following doubly linked list: (4 marks)
10
20
30
Head
11
while (Cur!=Head){ // 1 mark cout << Cur->data << ; // 1 mark Cur = Cur->prev; // 1 mark } cout << endl; } b) Write a function to add a node at the end of a doubly linked list with dummy head node.(7 marks)
void insertEnd(NodePtr& Head, int item){ // please add your code here
Answer(7 marks, 1 for each line): void insertEnd(NodePtr& Head, int item){ NodePtr New,Cur; New = new Node; New->data = item;
12
c) Somebody has built a partially doubly linked list(Figure 1) by using only the first two member variables of the node, data and the next pointer, while leaving the prev pointer unused. In Figure 1, Head is a pointer pointing to the dummy head.
10
20
30
Head Figure 1
Now write a function to convert the above partially doubly linked list into a doubly linked list. It should take the Head pointer of a partially doubly linked list(as shown in Figure 1), and return the head of the doubly linked list(as shown in Figure 2). Use what we have already got, DO NOT allocate any new nodes. (7 marks)
10
20
30
Head Figure 2
NodePtr convertToDoubly(NodePtr Head){ // please add your code here. // DO NOT build the doubly linked list from scratch.
Answer(7 marks): NodePtr convertToDoubly(NodePtr Head){ NodePtr ptr1 = Head; NodePtr ptr2 = Head->next; do{ // 1 mark // 1 mark]
13
14
x.add (3.9); if (x.code == y.code) cout << "Same code!" << endl; else cout << "Different code." << endl; return 0; }
Answer: (3 marks, 1 for each) HKD 16.8 EUR 100.5 HKD 2.3 c) The member function exchange is used to buy a foreign currency under a specified exchange rate using the amount of money stored in an object. For example:
Currency dollar = Currency(10, "USD"); Currency cad = dollar.exchange("CAD", 1.1969);
Then cad.amount == 11.969 and cad.code == "CAD". Write the implementation of the member function "exchange". The data in the original object should not be modified by this function. (5 marks)
Answer: (5 marks) Currency Currency::exchange(string newCode, double rate) { // 1 mark // should not modify any data members; otherwise, zero mark double new_amount = amount * rate; // 1 mark
15
16
Answer: (1 mark) return (head = = NULL); Its also fine with return (length()==0);
17
// 0.5 pt // 0.5 pt
c) Complete the implementation of the member function addElement(int item) that adds the given element to the list in increasing order (6 marks):
void OrderList::addElement(int item){ Nodeptr newp, cur, pre; pre = NULL; cur = head; // first, find the position cur and pre while( (cur != NULL) && (item>cur->data)){ pre = cur; cur = cur->next; } if ((cur == NULL) || (item != (cur->data))) { // second, if the element is not already in the list // create and insert the element right before cur
} // end of if
18
} // end of function
Answer: (6 marks) newp = new Node; // 1 mark for creation newp->data = item; // if dont treat special case, 3 marks
If (pre == NULL){ // 1 mark newp->next = head; // 1 mark head = newp; // 1 mark } else { pre->next = newp; // 1 mark new->next = cur; // 1 mark }
d) Implement the copy constructor, which takes a list and makes a copy of it. You can use addElement() method as defined in the previous question. (4 marks)
OrderList::OrderList(const OrderList& list){
Answers: (4 marks) head = NULL; // 0.5 mark Nodeptr cur = list.head; // 0.5 mark while(cur != NULL) { // 1 mark addElement(cur->data); // 1 mark cur = cur->next; // 1 mark }
19
e) The method merge is supposed to merge the two ordered lists into one ordered list. For example, there is an ordered integer list, list1, and another list, list2, list1.merge(list2) will return the merged list. Both list1 and list2 will not be changed after merging. Write the implementation of this member function. You can use the member function void addElement(int data) that has been already defined. (8 marks)
OrderList OrderList::merge(const OrderList& list2) const {
20
Answer: (8 marks) Solution 1: OrderList OrderList::merge(const OrderList& list2) const { Nodeptr Cur1, Cur2; Cur1 = head; Cur2 = list2.head; // proper declaration/initialization, 1 mark OrderList result; // creation of result 1 mark // totally 2 marks for the first part of result while((cur2 != NULL) { // 1 mark result.addElement(Cur2->data); // 0.5 mark Cur2 = Cur2->next; // 0.5 mark } // or OrderList result(list2); // totally 3 marks for the second part while((cur1 != NULL) { // 1 mark result.addElement(Cur1->data); // 1 mark Cur1 = Cur1->next; // 1 mark } return result; } Solution 2: this solution totalizing 11 marks is more difficult than the first one, but more efficient. We will try to give as many as marks we can up to 8. use addEnd instead of addElement is correct (even better), but not addHead OrderList OrderList::merge(const OrderList& list2) const { Nodeptr Cur1, Cur2; Cur1 = head; Cur2 = list2.head; // 1 mark // the algorithm consists of 2 major parts. // 1 mark
OrderList result; // // // //
// 1 mark
first, we examine two lists element by element. Each time, we compare the beginning elements of the two lists, take the smaller one, add it to the resulting list, and move forward for the following elements.
21
while ((Cur1 != NULL) && (Cur2 != NULL)){ // condition: 1 marks if (Cur1->data > Cur2->data){ // 1 mark result.addElement(Cur2->data); // 0.5 mark Cur2 = Cur2->next; // 0.5 mark } else { result.addElement(Cur1->data); // 0.5 mark Cur1 = Cur1->next; // 0.5 mark } }
// second, // there may still be elements left over in one of the lists, // we add these remaining elements in the final result. while (Cur1 != NULL) { // 1 mark result.addElement(Cur1->data); // 0.5 mark Cur1 = Cur1->next; // 0.5 mark } while (Cur2 != NULL) { // 1 mark result.addElement(Cur2->data); // 0.5 mark Cur2 = Cur2->next; // 0.5 mark } return result; } // 1 mark
f) Explain the meaning of two const in the prototype of the function merge. (2 marks)
OrderList OrderList::merge(const OrderList& list2)
const
22
(2) (1 mark) the second const at the end of the line after the closing parenthesis:
Answer: (2 marks, 1 for each) (1) The const before OrderIntList& is to ensure object list1 (or calling object) won be altered. (2) The const at last of the function merge is to ensure the object itself does not change.
23