Sheet4 Linked-Lists S2018 - Solution

You might also like

Download as pdf or txt
Download as pdf or txt
You are on page 1of 8

Data Structures & Algorithms 1st Year Sheet #4 - solution

Cairo University
Faculty of Engineering
Computer Engineering Department
Data Structures and Algorithms
Sheet #4 - Solution Commented [E1]: The problems is divided as follows:
P1 to P4: compare between array and linked list

Linked List P5 to P8: more practice on linked list


P9 to P11: do not allocate/deallocate new nodes if not
needed, sometimes you need just to manipulate pointers in
linked list.
P12: circular linked list
[Assumptions]: It’s intended to cover
This sheet presents some general operations that can be made on a general linked 1- all linked list operations: insert/delete/traverse
list (NOT specific for Bag ADT or List ADT). 2- pointer manipulations without making not needed
allocations.
Commented [E2]:
The sheet solution mentions the algorithm of the solutions (not the C++ code). This sheet is only for linked list algorithms
Given the head of the linked list, write the algorithm to solve the problem. and the lab is left for C++ syntax.
---------
Note the difference:
All sheet problems assume that Node has “data” (item) and pointer “next”. Return  is for the return statement of the function (if any)
Post-State  is for any other changes, like printing or
The linked list itself is represented by a pointer to list head. changing in inputs passed by reference like changing in the
NOTE: (READ the comments written in green  Important) input linked list

1. Write an algorithm that traverses a list and counts the number of negative elements. Give an Commented [E3]: Just a simple traversal problem.
array and a linked list implementation. Traversal in arrays is by using:
index and index++.
Input: Linked List L Input: Array L of size n Traversal in linked lists is by using:
Return: count of negative elements Return: count of negative elements pointers and pointer = pointer->next.
Pre-State: none Pre-State: none In linked lists, you don’t need to pass no. of elements to know
Post-State: none Post-State: none the end of it, linked lists ends with null.

In linked lists, you need to make sure of working in special


Algorithm NegCount(L) Algorithm NegCount(L, n) cases like 0, 1, 2 elements.
ptr = L , count = 0 count = 0 It’s simple to figure out the needed special cases from the
while (ptr) for i = 0 to n-1 condition of the main loop.
while(ptr->next)  special case is if(ptr==NULL)
if (ptr->data < 0) Increment count if (L[i]<0) Increment count;
ptr = ptr->next return count There is another type of special cases, ex: the something
you’re searching or looking for is at the 1st element or at last
return count element of the list or in many consecutive nodes.

In linked lists common mistake is when to try


ptr->data or ptr->next while ptr=NULL;
2. Write an algorithm that finds the minimum value in a list. Give an array and a linked list
implementation. Commented [LW4]:
It should be noted that linked lists are better in the insertion
and deletion since we don’t need to shift the elements in both
Input: Linked List L Input: Array L of size n cases or reallocation of the array with larger/smaller size.
Return: minimum value Return: minimum value However, arrays are better in accessing specific elements
Pre-State: none Pre-State: none O(1), since it doesn’t include the additional cost of following
Post-State: none Post-State: none the pointers as in the lists O(n).

Algorithm GetMin(L) Algorithm GetMin(L, n)


ptr = L min=L[0]
if (ptr) for i = 1 to n-1 Commented [LW5]: To check first that the list isn’t NULL.
min=ptr->data if (L[i]<min) min=L[i] You can also give them the algorithm without this if, then ask
them what happens if the list is null? Will the algorithm work
ptr=prt->next return min correctly?
while (ptr) Then ask them how to correct the algorithm to work correctly.
if (ptr->data < min) min=ptr->data Commented [LW6]: Ask the students what happens if the
ptr = ptr->next list contains 1 node only. Will this algorithm work correctly?
The answer is yes, because if we have one node, the
return min algorithm will not enter the while loop and it will return the
value in the first node.

CMP 102 & CMP N102 1/8 Spring 2018


Data Structures & Algorithms 1st Year Sheet #4 - solution

3. You are given two lists L and P containing integers sorted in ascending order. Write an Commented [E7]: This problem is to compare accessing
algorithm PrintLots(L,P) that will print elements in L that are in positions specified by P. e.g. if P by index in array and linked list.
In array: O(1)  Random Access
= 1, 3, 4, 6, the elements in positions 1, 3, 4, 6 in list L are printed. Give an array and a linked In linked list: O(n)  Sequential Access
list implementation.
Input: Linked List L, P Input: Array L of size n, P of size m
Return: none Return: none
Pre-State: L, P are sorted asc Pre-state: L, P are sorted asc
Post-State: printing L’s elements that are in the Post-state: printing L’s elements that are
positions of P’s elements in the positions of P’s elements
Algorithm PrintLots(L, P) Algorithm PrintLots(L, n, P, m)

lPtr = L // L is the head of the first list //Loop on P array


pPtr = P// P is the head of the second list for i = 0 to m-1
//check that position to be printed is inside
while(pPtr && pPtr->data <0) // Skip all negative positions
pPtr = pPtr->next if(P[i] >= 0 && P[i] < n)
print L[P[i]]
i = 0 // dummy index increased when lptr=lptr->next
while(lPtr && pPtr) // while until any (L or P) ends
index = pPtr->data // the above check:
// (checking if pPtr is not NULL)
// is needed before accessing
// pPtr->data
if (index == i)
print lPtr->data
//go to next position in P
pPtr = pPtr->next
//go to next L element
lPtr = lPtr->next
Increment i

4. You are given a sorted list L. Write an algorithm that completes L to become a list of Commented [E8]: This problem is to compare inserting
consecutive numbers by inserting the missing numbers between each two numbers in the elements in array and linked list.
In array: O(n)
original list. For example if L={2, 5, 7} in the above example, L will be {2, 3, 4, 5, 6, 7}. Give an In linked list: O(n)
array and a linked list implementation. but in arrays:
if (size < capacity)
The Linked List Implementation -shifting elements and increasing size
Input: Linked List L else
Return: none -reallocating new array with larger size
//reallocating is an expensive process
Pre-State: L is sorted asc -copy elements with the new element in to the new array
Post-State: L contains consecutive numbers In linked lists:
If we have the pointer where we want to insert the element,
by inserting the numbers between each two numbers in the list inserting it will be in O(1).
Commented [E9]: Array implementation is a harder
Algorithm Completes(L) algorithm because you’ll need to shift elements for every
IF(!L) return // if List is empty  nothing to insert inserted number and the capacity may be reached, so
ptr = L reallocation with bigger size will be needed.
Some optimizations on the brute force algorithm maybe done
while(ptr→next ) but still much harder than linked list.
From = ptr→data
To = ptr → next → data
While(To > From+1) // some values are missing
newNode = new Node // allocate new node and insert it
newNode→data = From + 1
newNode→next = ptr→next
ptr→next = newNode;

Increment “From”
ptr = ptr→next

CMP 102 & CMP N102 2/8 Spring 2018


Data Structures & Algorithms 1st Year Sheet #4 - solution

ptr = ptr → next;

5. Write an algorithm that traverses a list implemented using a linked list and deletes all nodes Commented [E10]: This is an exercise on deleting
elements
whose keys are negative. Think about these cases and see if the algorithm will handle
them
-empty list
Input: Linked List L -list of 1 positive element
Return: none -list of one negative element
-list of 2 elements: negative then positive
Pre-State: none -list of 2 elements, positive then negative,
Post-State: all L’s negative elements are deleted -list of ALL negative items

Algorithm DeleteNegatives(L)
if (!L ) return // Empty list
ptr = L
while (L && L->data < 0) // Remove all -ve items from the head
// NOTE: writing (L) BEFORE (L->data < 0) is important.
// because L must be check for being not NULL before accessing its -> “data”
ptr = L
L = L -> next
delete ptr

if(L == NULL) return // All item were -ve,

// If we reached here without a return,


// then we have at least one non-negative node
prev = L
ptr = prev->next

while (ptr) // ends when ptr points to NULL


if (ptr->data < 0)
prev->next = ptr -> next
delete ptr
else
prev=ptr
ptr = prev->next

6. Write an algorithm that appends two lists L1 and L2 together. After executing the algorithm, the Commented [E11]: Appending here is made in one line
appended list should be in L1 while L2 should be empty. Use linked list implementation. after reaching the last element of L1
(Pointers Manipulation)
Note: you don’t need to allocate/deallocate any new nodes.

Input: Linked Lists L1, L2


Return: none
Pre-State: none
Post-State: L1 = L1 + L2, L2 is empty (‘+’ here means appending)
Algorithm Appends(L1, L2)

ptr1 = L1 ptr2 = L2 L2 = NULL // head of L2 must be passed by Ref

// the special condition that will change heads


if (!ptr1) // L1 is empty
L1 = ptr2 // head of L1 must be passed by Ref
return

while (ptr1->next) // ends when ptr1 points to last element


ptr1 = ptr1->next

ptr1->next = ptr2 // the appending here


CMP 102 & CMP N102 3/8 Spring 2018
Data Structures & Algorithms 1st Year Sheet #4 - solution

7. Write an algorithm that appends a list to itself so that the resulting list contains two copies of the
original list. For example if input list is L={10, 2, 14}, the result is L= {10, 2, 14, 10, 2, 14}. Use
linked list implementation.

Input: Linked List L


Return: none
Pre-State: none
Post-State: L = L + L (‘+’ here means appending)

Algorithm Appends(L)
p1 = L

if (!p1) return; // if L is empty

head2 = new Node


head2 ->data = p1->data
if(!p1→next) //List has only one node
p1→next = head2;
head2→next = NULL
return

p2 = head2 // p2 is a moving pointer on the new list


// always pointing on the last element of the new list

while (p1→next) //ends when p1 points to last element


// create new node
N = new Node;
N→data = p1→next →data;

// connect it with p2 and makes p2 points to it


p2→next = N
p2 = N
p1 = p1→next

// insert last element


N = new Node
N→data = p1→data
p2→next = N

N->next = NULL // ends the 2nd list with NULL


p1->next = head2 // appends the new list to the original one

CMP 102 & CMP N102 4/8 Spring 2018


Data Structures & Algorithms 1st Year Sheet #4 - solution

8. Write an algorithm that swaps (exchanges) two nodes in a list. The nodes are identified by Commented [E12]: Swapping here can be made only with
numbers indicating their index. For example, to exchange nodes of index: 5 and 8, you would pointers manipulation without using temp data variable.
This manipulation is definitely better to be made if the data
call swap (5, 8), the smallest index is passed first. If the exchange is successful, the algorithm has a large size.
returns true. If it encounters an error, such as an invalid node number, it returns false. You can tell them about that and leave it as exercise.
Use linked list implementation.
Note: this swapping can be made using temp data variable and can be used using just pointers
manipulation without creating temp data variable. Try both methods and tell which is better if the
stored data has a large size.
Input: Linked List L, index1, index2
Return: returns true if swapping is done, false otherwise
Pre-State: -
Post-State: elements of index1 and index2 in linked list L are swapped if possible
Algorithm Swap(L, index1, index2)

ptr = L

if (!ptr || index1 > index2) return false

i = 0 // dummy index increased when ptr=ptr->next


ptr1 = ptr2 = NULL // pointers that will point to the 1st and 2nd passed indexes
while (ptr)
if (i == index1)
ptr1 = ptr
if (i == index2) //not ‘else if’ to handle if index1 = index2
ptr2 = ptr
ptr = ptr->next
increment i

if (!ptr1 || !ptr2) //means an index not found special case


return false;

//perform swapping
temp = ptr1->data
ptr1->data = ptr2->data
ptr2->data = temp
return true

CMP 102 & CMP N102 5/8 Spring 2018


Data Structures & Algorithms 1st Year Sheet #4 - solution

9. Write a function that merges two ordered lists L1 and L2 implemented as linked lists into one Commented [E13]: Pointer manipulation problem.
linked list. When the two lists are merged, the data in merged list are also ordered. Do not
remove duplicates if found. Write a function for each case of the following:
a. The merged list should be a new list L3. L1 and L2 should be left unchanged.
b. Put the merged list in L1 and make L2 empty.
[Constraint]: don’t create or delete any new nodes.

Solution for part (b)


Input: Linked List L1, L2
Return: none
Pre-State: L1, L2 are sorted asc
Post-State:
-L1 = L1 merged with L2
-L2 is empty
-L1 is sorted asc and duplicates are remained.
Algorithm MergeSorted(L1, L2)
ptr1 = L1
ptr2 = L2
L1 = NULL // will be filled
L2 = NULL // L2 is empty
ptr3 = NULL // points to current last element in merged list
while(ptr1 && ptr2)
if(ptr1->data <= ptr2->data)
if(!ptr3) L1 = ptr1
else ptr3->next = ptr1
ptr3 = ptr1
ptr1 = ptr1->next
else
if(!ptr3) L1 = ptr2
else ptr3->next = ptr2
ptr3 = ptr2
ptr2 = ptr2->next
if(ptr1) // include remaining L1 (if not while)
if(!ptr3) L1 = ptr1
else ptr3->next = ptr1
if(ptr2) // include remaining L2 (if not while)
if(!ptr3) L1 = ptr2
else ptr3->next = ptr2

CMP 102 & CMP N102 6/8 Spring 2018


Data Structures & Algorithms 1st Year Sheet #4 - solution

10. Implement a function AlternatingSplit(...) that given a list L, splits it into two lists (L1 and Commented [E14]: Pointer manipulation.
L2) where the first node goes to L1, the second to L2, the third to L1, the fourth to L2 and so on.
At the end of this function, the input list should be pointing to NULL.
[Constraint]: don’t create or delete any new nodes.

Input: Linked List L, and empty Linked Lists L1, L2


Return: none
Pre-State: L1, L2 are empty
Post-State:
- L1 contains elements 1st, 3rd, 5th, …etc of L
- L2 contains elements 2nd, 4th, 6th, …etc of L
- L is empty
Algorithm AlternatingSplit(L, L1, L2)
L1 = L L2=NULL
if(! L) return // special case Empty List
if(! L->next) // L contains only 1 element special case
L = NULL
return
L2 = L->next // the above check is needed before this line
p1 = L1
p2 = L2
// Note: p1 will always point to the node before the node of p2 (p1 is the previous of p2)
while(p2)
p1->next = p2->next
p1 = p2
p2 = p2->next
L = NULL

11. Implement a function AlternatingMerge(...) that reverses what you made in the previous
problem; merges generated L1 and L2 into L.
[Constraint]: do not create or delete any new nodes.

Input: Linked Lists L1, L2 and empty linked list L


Return: L (the merge of L1 and L2 nodes taken alternatively)
Pre-State: L1 and L2 are of equal size or L1 is larger by 1
Because it’s mentioned in the question that they’re the output of problem 8
Post-State:
- L contains L1 elements in odd positions and L2 elements in even positions
- L1 is empty and L2 is empty
Algorithm AlternatingMerge(L1, L2, L)
ptr1 = L1 ptr2 = L2 L = ptr1
while(ptr1 && ptr2)
temp1 = ptr1->next
temp2 = ptr2->next
ptr1->next = ptr2
ptr2->next = temp1
ptr1 = temp1
ptr2 = temp2
L1 = NULL
L2 = NULL
Return L

CMP 102 & CMP N102 7/8 Spring 2018


Data Structures & Algorithms 1st Year Sheet #4 - solution

12. The Josephus problem is the following game: Commented [E15]:


N people numbered 1 to N are sitting in a circle. Starting at person 1, a hot potato is passed. It’s made by Circular Linked List.
If n = 6, so players p1 to p6
After M passes, the person holding the hot potato is eliminated, the circle closes ranks, and the and m = 3, the order of deletion is:
game continues with the person who was sitting after the one eliminated picking up the hot p4 -> p2 -> p1 -> p3 ->p6
Winner is p5.
potato. The last remaining person wins. Write an algorithm to solve the Josephus problem for
general M ad N.
For example:
If N = 6 (players are p1 to p6) and M = 3,
the order of deletion is: {p4 -> p2 -> p1 -> p3 ->p6}, winner is p5.

Input: Circular Linked Lists L


Output: -
Pre-State: L is circular linked list (the last element’s next points to the 1st element).
Post-State: If L wasn’t empty at the first place, L becomes containing only 1 element (will be
circular list too), the winner. All other elements are deleted.
Algorithm JosephusProblem(L)
ptr = L
if(!ptr) return // special case needed before ptr->next
while (ptr != ptr->next) // enter until only one circular element
for i = 0 to m-1
before = ptr
ptr = ptr->next
temp = ptr->next
delete ptr
before->next = temp
ptr = temp

13. Implement all the above problems in C++ and write an appropriate main function that calls your
functions and tests them.

CMP 102 & CMP N102 8/8 Spring 2018

You might also like