COMP2710: Software Construction - Linked list exercises
1. COMP 2710 Software Construction
Linked List – Exercises
Dr. Xiao Qin
Department of Computer Science and
Software Engineering
Auburn University
http://www.eng.auburn.edu/~xqin
xqin@auburn.edu
2. Exercise 1
1-2
• Task 1: Define a structure named node, where there are two
items – (1) data whose type is int and (2) a pointer pointing
to the next node
• Task 2: Using typedef to define a new type (e.g., nodePtr)
of pointer pointing to node (i.e., node*)
• Task 3: Create a pointer (e.g., node_ptr) using the above new
data type
• Task 4: Allocate memory resource for the new pointer
• Task 5: Assign value (e.g., 10) to the node pointed by
node_ptr
3. Exercise 2: Print a list of nodes
struct node {
int data;
node *next;
};
typedef node* nodePtr;
void printList(nodePtr root);
What two cases should we consider?
4. Answer: Print a list of nodes
void printList(nodePtr root) {
nodePtr cur;
if (root == NULL)
cout << "This is an empty listn";
cur = root;
while (cur != NULL) {
cout << cur->data << endl;
cur = cur->next;
}
}
5. Exercise 3:
Insert a node to the head of the list
struct node {
int data;
node *next;
};
typedef node* nodePtr;
void insertNode(nodePtr& root, int info);
//Another possible prototype
void insertNode(nodePtr& root, nodePtr newNodePtr);
What is the difference between the above two prototypes?
How many cases should we consider? What are these cases?
6. Exercise 3 - Insert a node to the head of the list
1-6
struct node {
int data;
node *next;
};
typedef node* nodePtr;
void insertNode(nodePtr& root, int info);
root
cur_ptr
11
22 33
info
44
55
66
7. Exercise 3: Answer
Insert a node to the head of the list
void insertNode(nodePtr& root, int info) {
nodePtr cur_prt;
cur_ptr = new node; //Do not use this: new nodePtr
assert(cur_ptr != NULL); //Ensure that memory is allocatd
cur_ptr->data = info;
cur_ptr->next = NULL;
if (root == NULL) //For empty list, cur_ptr becomes the root
root = cur_prt;
else { //Insert cur as the root of the list
cur_ptr->next = root;
root = cur_ptr;
}
}
8. Exercise 4: Insert a node to the
end of the list
1-8
struct node {
int data;
node *next;
};
typedef node* nodePtr;
void appendNode(nodePtr& root, int info);
How many cases should we consider? What are these cases?
9. Exercise 4 - Insert a node to the end of the list
1-9
struct node {
int data;
node *next;
};
typedef node* nodePtr;
void appendNode(nodePtr& root, int info);
root
new_ptr
11
22 33
info
44
55
cur_ptr
6.16.1
6.26.2
10. void appendNode(nodePtr& root, int info) {
nodePtr new_ptr;
nodePtr cur_ptr;
new_ptr = new node; //Do not use this: new nodePtr
assert(new_Ptr != NULL); //Ensure that memory is allocatd
new_ptr->data = info;
new_ptr->next = NULL;
if (root == NULL) //For empty list, new_ptr becomes the root
root = new_ptr;
else { //Append the new node at the end of the list
cur_ptr = root;
while (cur_ptr->next != NULL)
cur_ptr = cur_ptr->next;
cur_ptr->next = new_ptr;
}
}
11. Exercise 5: Delete the head node
of the list
1-11
struct node {
int data;
node *next;
};
typedef node* nodePtr;
void deleteHead(nodePtr& root);
How many cases should we consider? What are these cases?
12. Exercise 5 - Delete the head node of the list
1-12
struct node {
int data;
node *next;
};
typedef node* nodePtr;
void deleteHead(nodePtr& root);
root
22
11 curPtr
33
13. void deleteHead(nodePtr& root) {
nodePtr cur_ptr;
if (root != NULL) {
cur_ptr = root; //Deleted node must be returned to OS
root = root->next;
delete cur_ptr;
}
else
cout << "This is an empty list. No deletion!n";
}
14. Review: Linked List
struct node {
int data;
node *next;
};
typedef node* nodePtr;
void insertNode(nodePtr& root, int info);
void appendNode(nodePtr& root, int info);
void deleteHead(nodePtr& root);
15. Exercise 6:
Delete the last node in the list
1-15
struct node {
int data;
node *next;
};
typedef node* nodePtr;
void deleteTail(nodePtr& root);
How many cases should we consider? What are these cases?
1.Implement the function
2.Write a test driver
16. Exercise 6 - Delete the last node in the list
1-16
struct node {
int data;
node *next;
};
typedef node* nodePtr;
void deleteTail(nodePtr& root);
root
11
22
33
pre_ptr cur_ptr
44
17. void deleteTail(nodePtr& root) {
nodePtr cur_prt, pre_ptr;
//There are three cases:
if (root == NULL) //Empty list
cout << "This is an empty list. No tail is deleted!n";
else {
if (root->next == NULL) { //List has one node
free(root); //or delete root;
root = NULL;
}
else { //List has more than one node
pre_ptr = root;
cur_ptr = root->next;
while (cur_ptr->next != NULL) {
pre_ptr = cur_ptr;
cur_ptr = cur_ptr->next;
}
pre_ptr->next = NULL;
delete cur_ptr; //or delete cur, pointing at the last node
}
}
}
18. Exercise 7:
Delete a specified node in the list
1-18
struct node {
int data;
node *next;
};
typedef node* nodePtr;
void deleteNode(nodePtr& root, int info);
How many cases should we consider? What are these cases?
1.Implement the function
2.Write a test driver
19. Exercise 7 - Delete a specified node in the list
1-19
void deleteNode(nodePtr& root, int info);
root
11
22
33
cur_ptr
44
pre_ptr
NULL
find
20. void deleteNode(nodePtr& root, int info) {
nodePtr cur_ptr, pre_ptr;
if (root == NULL) //Empty list
cout << "This is an empty list. No node is deleted!n";
else {
pre_ptr = NULL; cur_ptr = root;
while (cur_ptr != NULL) { //cur_ptr->next != NULL is Bug 1: coredump
if (cur_ptr->data != info) { //compare and does not match
pre_ptr = cur_ptr;
cur_ptr = cur_ptr->next;
}
else { //match and delete node pointed by cur
if (pre_ptr == NULL) { //cur is pointing to the first node
root = root->next;
delete cur_ptr;
cur_ptr = root;
}
else { //cur_ptr is NOT pointing to the first node
pre_ptr->next = cur_ptr->next;
delete cur_ptr;
cur_ptr = pre_ptr->next;
}
}
Hinweis der Redaktion
Programming Language: C or C++
Spring’15: slides 14-16 - See also Lec08c2-Lnked List Exercise 1.ppt
Empty List
Non-empty list
void printList(nodePtr root) {
nodePtr cur;
if (root == NULL)
cout &lt;&lt; &quot;This is an empty list\n&quot;;
cur = root;
while (cur != NULL) {
cout &lt;&lt; cur-&gt;data &lt;&lt; endl;
cur = cur-&gt;next;
}
}
Empty List
Non-empty list
void printList(nodePtr root) {
nodePtr cur;
if (root == NULL)
cout &lt;&lt; &quot;This is an empty list\n&quot;;
cur = root;
while (cur != NULL) {
cout &lt;&lt; cur-&gt;data &lt;&lt; endl;
cur = cur-&gt;next;
}
}
void insertNode(nodePtr& root, int info) {
nodePtr cur;
cur = new node; //Do not use this: new nodePtr
assert(cur != NULL); //Ensure that memory is allocatd
cur-&gt;data = info;
cur-&gt;next = NULL;
if (root == NULL) //If the list is empty, cur becomes the root
root = cur;
else { //Insert cur as the root of the list
cur-&gt;next = root;
root = cur;
}
}
void appendNode(nodePtr& root, int info) {
nodePtr cur;
nodePtr pre;
cur = new node; //Do not use this: new nodePtr
assert(cur != NULL); //Ensure that memory is allocatd
cur-&gt;data = info;
cur-&gt;next = NULL;
if (root == NULL) //If the list is empty, cur becomes the root
root = cur;
else { //Append the new node at the end of the list
pre = root;
while (pre-&gt;next != NULL)
pre = pre-&gt;next;
pre-&gt;next = cur;
}
}
void insertNode(nodePtr& root, int info) {
nodePtr cur;
cur = new node; //Do not use this: new nodePtr
assert(cur != NULL); //Ensure that memory is allocatd
cur-&gt;data = info;
cur-&gt;next = NULL;
if (root == NULL) //If the list is empty, cur becomes the root
root = cur;
else { //Insert cur as the root of the list
cur-&gt;next = root;
root = cur;
}
}
void appendNode(nodePtr& root, int info) {
nodePtr cur;
nodePtr pre;
cur = new node; //Do not use this: new nodePtr
assert(cur != NULL); //Ensure that memory is allocatd
cur-&gt;data = info;
cur-&gt;next = NULL;
if (root == NULL) //If the list is empty, cur becomes the root
root = cur;
else { //Append the new node at the end of the list
pre = root;
while (pre-&gt;next != NULL)
pre = pre-&gt;next;
pre-&gt;next = cur;
}
}
void appendNode(nodePtr& root, int info) {
nodePtr cur;
nodePtr pre;
cur = new node; //Do not use this: new nodePtr
assert(cur != NULL); //Ensure that memory is allocatd
cur-&gt;data = info;
cur-&gt;next = NULL;
if (root == NULL) //If the list is empty, cur becomes the root
root = cur;
else { //Append the new node at the end of the list
pre = root;
while (pre-&gt;next != NULL)
pre = pre-&gt;next;
pre-&gt;next = cur;
}
}
void deleteHead(nodePtr& root);
void deleteHead(nodePtr& root) {
nodePtr cur;
if (root != NULL) {
cur = root; //Deleted node must be returned to the OS
root = root-&gt;next;
delete cur;
}
else
cout &lt;&lt; &quot;This is an empty list. No head is deleted!\n&quot;;
}
void appendNode(nodePtr& root, int info) {
nodePtr cur;
nodePtr pre;
cur = new node; //Do not use this: new nodePtr
assert(cur != NULL); //Ensure that memory is allocatd
cur-&gt;data = info;
cur-&gt;next = NULL;
if (root == NULL) //If the list is empty, cur becomes the root
root = cur;
else { //Append the new node at the end of the list
pre = root;
while (pre-&gt;next != NULL)
pre = pre-&gt;next;
pre-&gt;next = cur;
}
}
void insertNode(nodePtr& root, int info) {
nodePtr cur;
cur = new node; //Do not use this: new nodePtr
assert(cur != NULL); //Ensure that memory is allocatd
cur-&gt;data = info;
cur-&gt;next = NULL;
if (root == NULL) //If the list is empty, cur becomes the root
root = cur;
else { //Insert cur as the root of the list
cur-&gt;next = root;
root = cur;
}
}
void deleteTail(nodePtr& root) {
nodePtr cur, pre;
if (root == NULL) //Empty list
cout &lt;&lt; &quot;This is an empty list. No tail is deleted!\n&quot;;
else {
if (root-&gt;next == NULL) { //List has one node
free(root);
root = NULL;
}
else { //List has more than one node
pre = root;
cur = root-&gt;next;
while (cur-&gt;next != NULL) {
pre = cur;
cur = cur-&gt;next;
}
pre-&gt;next = NULL;
free(cur); //delete cur, which is pointing at the last node
}
}
}
void appendNode(nodePtr& root, int info) {
nodePtr cur;
nodePtr pre;
cur = new node; //Do not use this: new nodePtr
assert(cur != NULL); //Ensure that memory is allocatd
cur-&gt;data = info;
cur-&gt;next = NULL;
if (root == NULL) //If the list is empty, cur becomes the root
root = cur;
else { //Append the new node at the end of the list
pre = root;
while (pre-&gt;next != NULL)
pre = pre-&gt;next;
pre-&gt;next = cur;
}
}
void deleteNode(nodePtr& root, int info) {
nodePtr cur, pre;
if (root == NULL) //Empty list
cout &lt;&lt; &quot;This is an empty list. No node is deleted!\n&quot;;
else {
pre = NULL;
cur = root;
while (cur != NULL) { //cur-&gt;next != NULL is Bug 1 - core dump occur
if (cur-&gt;data != info) { //compare and does not match
pre = cur;
cur = cur-&gt;next;
}
else { //match and delete node pointed by cur
if (pre == NULL) { //cur is pointing to the first node
root = root-&gt;next;
delete cur;
cur = root;
}
else { //cur is NOT pointing to the first node
pre-&gt;next = cur-&gt;next;
delete cur;
cur = pre-&gt;next;
}
}
}
//Bug 2: With the following two statement, only when delete one-node list, can core dump occur
//pre-&gt;next = NULL; //adding these two statements - core dump occur
//delete cur; //delete cur, which is pointing at the last node
}
}
void appendNode(nodePtr& root, int info) {
nodePtr cur;
nodePtr pre;
cur = new node; //Do not use this: new nodePtr
assert(cur != NULL); //Ensure that memory is allocatd
cur-&gt;data = info;
cur-&gt;next = NULL;
if (root == NULL) //If the list is empty, cur becomes the root
root = cur;
else { //Append the new node at the end of the list
pre = root;
while (pre-&gt;next != NULL)
pre = pre-&gt;next;
pre-&gt;next = cur;
}
}