0% found this document useful (0 votes)
22 views6 pages

Practical Lab I: Review of Data Structures

This document discusses data structures and algorithms. It defines an algorithm, gives examples, and distinguishes between data abstraction and data structures. It also discusses recursion, provides examples where it is used, and analyzes the tradeoffs of recursion. Finally, it covers tree traversal, breadth-first search, depth-first search, and works through examples applying these concepts.

Uploaded by

kentlewa
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
22 views6 pages

Practical Lab I: Review of Data Structures

This document discusses data structures and algorithms. It defines an algorithm, gives examples, and distinguishes between data abstraction and data structures. It also discusses recursion, provides examples where it is used, and analyzes the tradeoffs of recursion. Finally, it covers tree traversal, breadth-first search, depth-first search, and works through examples applying these concepts.

Uploaded by

kentlewa
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 6

PRACTICAL LAB I: REVIEW OF DATA STRUCTURES

1)
Explain the following terms and give examples of each

i. An algorithm is a set of steps that must be followed in a specific order to


complete a task.
Examples of algorithms:
I. Searching for a word in a dictionary: The algorithm for this task is to start at
the beginning of the dictionary and compare the word you are searching for to each
word in the dictionary, one by one. If you find a match, you return the word's
definition. If you reach the end of the dictionary without finding a match, you return
an error message.
II. Sorting a list of numbers: The algorithm for this task is to compare each
number in the list to the number next to it. If the first number is greater than the
second number, you swap the two numbers. You continue this process until no more
swaps are necessary.
III. Cooking a cake: The algorithm for this task is to preheat the oven, mix the
ingredients together, pour the batter into a cake pan, and bake the cake for a certain
amount of time.

2) Distinguish between data abstraction and data structures with the aid of appropriate
examples
I. Data Abstraction is like using a black box. You don't need to know how it
works inside, just what it does. It hides the complicated details and focuses on what
you can do with the data, not how it's stored or manipulated.
Example of Data Abstraction: Imagine a TV remote control. You press buttons to
change channels, volume, or power on/off. You don't need to know how the remote
works internally; you abstract away the complexity. All you care about is the
functions it provides.
II. Data Structures, on the other hand, are about organizing and storing data in a
specific way to make it efficient to access and manipulate. They are the tools and
mechanisms for dealing with data in a more structured manner.
Example of Data Structures: Think of a bookshelf. It's a structure designed to store
books efficiently. Each shelf can hold a specific number of books, and you can easily
find and access a book by its position. In this case, the bookshelf is the data structure,
and the books are the data.

3)
i) Discuss the motivation behind the use of recursion in programming

Recursion is a programming technique where a function calls itself directly or


indirectly. It is a powerful tool that can be used to solve a variety of problems.

reasons to use recursion:

I. Recursion can offer simpler and more elegant solutions compared to iteration.
Take the factorial problem, for instance. The recursive approach is cleaner and
more straightforward than the iterative one.
II. Recursion can provide better efficiency in certain cases. Consider the merge
sort algorithm; its recursive version outperforms the iterative one for large arrays.
III. Recursion is ideal for solving complex problems that are challenging to
address iteratively. Think about tree traversal: the recursive solution is far more
readable and intuitive than an iterative one.

Drawbacks to using recursion:

I. Recursion can be difficult to understand and debug. It can be hard to keep


track of all the different function calls that are happening at the same time.
II. Recursion can be inefficient for some problems. For example, the recursive
solution to the Fibonacci sequence problem is much less efficient than the iterative
solution.
III. Recursion can lead to stack overflows. If a recursive function calls itself too
many times, the call stack will overflow and the program will crash.

Examples of problems that are often solved using recursion:


1. Factorial
2. Fibonacci sequence
3. Tree traversal
4. Merge sort
5. Quicksort
6. Towers of Hanoi

i) Consider the following recursive definition:

n+1 if m=0
Acker (m, n) = Acker (m-1, 1) if n=0
Acker (m-1, Acker (m, n-1)) otherwise

This function, called Ackermann’s function, is of interest because it grows rapidly


with respect to the sizes of m and n.

(1) What is Acker (1, 2)? Show your working

Acker (1, 2) → Acker (0, Acker (1, 1))


Acker (0, Acker (1, 1)) → Acker (0, Acker (0, 1))
Acker (0, Acker (0, 1)) → Acker (0, 1)
So, Acker (1, 2) = Acker (0, 1) = 1.

(2) Write a program in C/C++/Java to implement the function and test Acker (1,2).
In C
#include <stdio.h>

// Function to calculate the Acker function


int Acker(int m, int n) {
// Base case 1
if (m == 0) {
return n + 1;
}
// Base case 2
else if (m > 0 && n == 0) {
return Acker(m - 1, 1);
}
// Recursive case
else if (m > 0 && n > 0) {
// Calculate Acker function recursively
int recursive1 = Acker(m, n - 1);
return Acker(m - 1, recursive1);
}
}

int main() {
int m = 1;
int n = 2;
int result = Acker(m, n);

printf("Acker(%d, %d) = %d\n", m, n, result);

return 0;
}

Compare the output with (I) above


Acker (1, 2) = 4
the output from the C program is consistent with the expected value of Acker (1,
2)
This output differs from the previous calculation (Acker (1, 2) = 1) because
Ackermann's function grows very quickly, and small changes in the input values
can lead to significantly different results. The recursive nature of this function
makes it computationally intensive, and it quickly becomes impractical for larger
input values.

4) Draw a binary Tree for the expression: A * B - (C + D) * (P / Q)


5) Traverse the tree in
i) In order
(Left-Root-Right); visit nodes from left to right
A * B - (C + D) * (P / Q)
ii) Preorder
(Root-Left-Right): visit the current node first, then its left subtree, and finally its right
subtree.
-*AB*+CD/PQ
iii) Post order traversals
(Left-Right-Root); visit the left subtree first, then the right subtree, and finally the
current node
AB*CD+PQ/*-
C) Consider the following digraph G where the alphabetic order of node names defines the
ordering of neighbors of each node
a) Show the order of visiting its nodes during the breadth-first search starting at A and
using the neighbor ordering mentioned above.

The order of visiting nodes during BFS starting at A is A, B, D, E, F, C, G.

b) Show the order of visiting its nodes during the depth-first search starting at A and
using the same neighbor ordering. Draw the resulting depth-first search tree.

Starting from A, we explore as far as possible along each branch before backtracking.
Visit A, Visit B, Visit E, Visit F (because it's the next neighbor based on alphabetic
order),Visit G, Backtrack to F, Visit C (next neighbor after F, Visit C (next neighbor after
F, Backtrack to B,
Visit D.

You might also like