0% found this document useful (0 votes)
11 views

AL CSC Notes - Part 3 (2023)

Uploaded by

ebaidetienoh
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
11 views

AL CSC Notes - Part 3 (2023)

Uploaded by

ebaidetienoh
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 52

9

ALGORITHM DESIGNAND PROGRAMMING CONCEPTS

Introduction explicit by specifying the type of the data. The type of a particular data
determines how many bits are used to store that data, and how the bits
Computer programs are written by analyzing problems, then designing
algorithms for the problems. An algorithm is a set of step-by-step instructions are to be interpreted and manipulated.
for solving a problem. Determining the right steps, following them correctly We can define the term data type as:
and completely are all part of the process of algorithm design. (i) A set of values and a collection of operations defined on them.
In order to be executed by computers, algorithms need to be in the form of a Or,
program. A program is written in a programming language, and the activity of (ii) An attribute of data which tells the computer how the
expressing an algorithm as a program is called programming. In algorithms, programmer intends to use the data.
steps are expressed in the form of instructions or statements. As a consequence, Or,
a computer program comprises a series of statements which indicate to the (iii) A data storage format that can contain a specific type or range
computer which operations to perform. The programming language used will of values.
dictate the nature of the statements in a program. It is important to understand
that algorithms are independent of the programming language used and each A data type specifies the set of values that data objects of that type may
algorithm can be expressed in different programming languages and executed have and the operations that define the possible manipulations that can
on different computers. be performed on these values. When data are assigned a type in a
programming language, they cannot be treated like another type under
9.1. Data Types normal circumstances.
Every program uses data, either explicitly or implicitly, to arrive at a Data types can be grouped into primitive data types, composite data
result. All programs specify a set of operations that are to be applied to types and abstract data types.
certain data in a certain sequence. Data stored in memory is a sequence
of bits (0 or 1). Consider the bit sequence 1000010. What does it 9.1.1. Primitive Data Types
represent? Primitive data types, also called simple data types, base
types, scalar types, unstructured types or elementary types,
66? are types whose elements consist of indivisible entities (a
single data value or attribute). Almost all programming
'B'?
languages provide a set of primitive data types, the most
9.2E-44? common being integer, real (float), character, string,
Boolean, and pointer.
How the computer interprets a sequence of bits depends on the context.
When we write computer programs, we have to make the context
__________________
© 2023/0795 CSC/Notes 1
No. Data Type Description and Examples Declaration Explanation

Used for storing negative and int age; age is an integer.


positive whole numbers, and mark is a real or
1 Integer
zero. float mark;
floating-point number
Examples: -97, 0,65, 123.
gender is declared as
Used for storing negative and char gender = 'M'; character and initialized
Real/Float/ positive numbers with a to M.
2
Double fractional part. name is a string that can
Examples:-12.5, 0.025, 3.14 char name[15] take a maximum of fifteen
Used for storing a single characters.
Character
3 character.
(Char)
Examples: 'a', 'B', '&', '6', NULL The basic elements of a specification of a data type are:

Used for storing a sequence of 1. The attributes that distinguish data objects and types
String/Text/ characters. (like number of bits used, how the bits will be stored and
4 interpreted)
Alphanumeric Examples: "hello world",
"computer", "ASCII" 2. The values that data objects of that type may have
3. The operations that define the possible manipulations on
Used for storing true or false
data objects of that type.
5 Boolean values.
Examples: True or False 9.1.2. Composite Data Types
Pointer/ Used for storing a memory A composite data type, also called compound data type or
6
Reference address. structured data type is a collection or grouping of multiple
data items into a single entity. That is, a composite data type
contains other data items as its elements or components.
Most programming languages require that the data type of
Examples of composite data types are arrays, records and
each data item be specified before they can be used. This is
linked lists.
known as declaration of variables. The declaration gives a
name and a data type for the variable or data item.
Arrays
For example: declaration of some variables in C
programming. An array is a collection of data items, all of the same type,
accessed using a common name. It is a finite list of
homogeneous data items. Each data item in an array is called
array element. We can have an array of integers, or an array
__________________
© 2023/0795 CSC/Notes 2
of characters or an array of anything that has a defined data For example:
type. An array has some fundamental properties that must be
specified when the array is created. int A[6];

Property Description A[0] A[1] A[2] A[3] A[4] A[5]

The name by which the array is


Name - The name of the array is A, its size is 6 and it’s of
identified.
The number of elements the array type integer.
Size
can hold. - The first element in the array has reference A[0]
Type
The data type of the elements of and the last element has reference A[5].
the array.
The number of indices, or Initializing a 1-D Array
subscripts, that you need in order
Dimension We can initialize the elements of a 1-D array in the
to specify an individual element of
the array. same way as the ordinary variables when they are
declared. The general form for declaring an array is:
(a) One-Dimensional Arrays
type array_name[size]={list of values};
A one-dimensional (1-D) array is an array in which
only one subscript is needed to specify a particular Examples:
element of the array. A one-dimensional array can be int A[6] = {4, 2, ,0, 5, 1, 3};
visually represented as a linear list.
4 2 0 5 1 3
0 1 2 3 5 8
int A[6] = {1, 2, 3};
Declaring a 1-D Array … In this declaration, the compiler initializes the first
We know that all data items are declared before they three locations with 1, 2 and 3, and the next three
are used in a program. Similarly, an array must be locations are automatically initialized to 0’s.
declared before it is used. During declaration, the size
of the array has to be declared. The size used during 1 2 3 0 0 0
declaration of the array informs the compiler to
allocate and reserve enough space in memory to hold char b[] = {'a', 'b', 'c', 'd'};
values in the array. The general form for declaring an
array is: … In this declaration, even though we have not
specified the size of the array, the size will be set to the
type array_name[size];
__________________
© 2023/0795 CSC/Notes 3
total number of initial values specified. So, the array Initializing a 2-D Array
size will be set to 6 automatically. Like one-dimensional arrays, two-dimensional arrays
may be initialized by following their declaration with a
a b c d list of initial values enclosed in braces.

int A[3][3]={1,2,3,4,5,6,7,8,9};
(b) Two-Dimensional Arrays
A two-dimensional (2-D) array is an array in which This declaration initializes the elements of the first
two subscripts are needed to specify a particular row with the values 1, 2 and 3,those of the second row
element of the array. A 2-D array is divided into rows with the values 4, 5 and 6 and those of the third row
and columns and is therefore well suited to handle a with values 7, 8 and 9. The initialization is done row
table of data. by row.
1 2 3
Declaring a 2-D Array
4 5 6
The syntax for declaring a 2-D array in C
programming is as follows: 7 8 9

type array_name[rows][cols];
The above declaration can also be written as:

Where rows is the number of rows in the array and


int A[3][3] = {{1,2,3},{4,5,6},
cols is the number of columns.
{7,8,9}};

Example: … the elements of each row are surrounded by braces.


int A[3][3];
Summary on Arrays
…will be represented visually as follows:
1. An array holds elements of the same data type.

Col 0 Col 1 Col 2 2. Array elements are stored in subsequent


(contiguous) memory locations.
Row 0 A[0][0] A[0][1] A[0][2]
Row 1 A[1][0] A[1][1] A[1][2] 3. Two-dimensional array elements are stored row-
by-row in subsequent memory locations.
Row 2 A[2][0] A[2][1] A[2][2]
4. An array’s name represents its base address. The
base address is the address of the starting/first

__________________
© 2023/0795 CSC/Notes 4
element in the array. In order to access the fields or members of a variable of type
record we use the member access operator (.).
5. Array indexing starts with 0 and ends with N-1,
where N is the size of the array.
Examples: Write,
student1.student_name
Records … to access the name of student1.
A record is a collection of related fields, possibly of different student2.age
types, having a single name. A record data structure allows … to access the age of student2.
data items of same or different types, which define a
particular object or entity, to be stored together. The fields of
Arrays of Records
a record are usually called members. Defining a record type
includes specifying a name by which the record can be Records can be held within a single array. This allows for
identified and the data type of each field. storage of more than one record within the same array.
In C programming, a record data type is called a structure Assume we want to store a list of students where each
which is denoted by the word struct. student has a name, a gender and an age. We can use an
array of records instead of using three simple arrays with
struct student_rec{ three data types (name – string, gender – character and age
– integer).
char student_name[15];
[0] [1] [2] [3] [4]
char gender;
int age; Name: Name: Name: Name: Name:
Gender: Gender: Gender: Gender: Gender:
}
Age: Age: Age: Age: Age:

The above record named student_rec consists of three


fields or members: student_name of type string, gender of A field in an array of records is accessed as follows:
type character and age of type integer.
array_name[index].field_name;
With the record type student_rec defined, we can
declare variables of the type student_rec as follows:
For example: Write,
struct student_rec student1, student2; A[2].gender
… to access the gender field of the record at index 2 in the
student1 and student2 are two variables which have array A.
type student_rec, meaning that both are records.

__________________
© 2023/0795 CSC/Notes 5
Question: with value 50 does not hold any address, so it holds the
value NULL.
1. In programming terms, what is the difference between an
array and a record?
Linked List Array
2. Give an example of EACH of:
- data that would best be handled as an array, Supports dynamic memory Supports static memory
- data that would best be handled as a record, allocation (dynamic data allocation (static data
- data that would best be handled as a combination
structure) structure)
Elements are stored in
of array and record. Elements can be stored
contiguous memory
anywhere in memory.
locations
Linked Lists Supports sequential access Supports random access
A linked list is a linear collection of data items in which each Insertion and deletion Insertion and deletion
item is connected to the next item via a link. Each item is operations are fast operations are slow
placed together with the link to the next item, resulting in a Memory is allocated in Memory is allocated in
simple component called a node. A node in a linked list is a heap section stack section
record that has at least two fields: a data field, which holds
the actual value to be stored in the node and a pointer field, 9.1.3. Abstract Data Types
which holds the address of the next node.
An abstract data type is a mathematical model for a
The entry point to a linked list is a pointer variable called the collection of data, which specifies the type of data stored, the
head. If the list is empty, then the head is a null pointer. A operations supported on them, and the types of parameters of
null pointer or null reference does not hold any address. It the operations. In other words, an ADT is a data structure
holds the value NULL. The last node in a linked list is also a (collection of data) with a well-defined interface
null pointer. (operations). The users of the ADT are constrained to
manipulate the ADT solely through the operations provided.
Head
The specification of an ADT indicates what the ADT
100 Data operations do and not how to implement them.
Implementing the ADT includes choosing a particular data
NULL structure. Examples of ADTs are stacks, queues, and binary
10 103 30 107 50
trees.

Pointer Stacks
A stack is a linear list in which items are added and removed
The head pointer holds the address 100. This means that the from the same end called top. Adding and removing items
node with value 10 is stored in the memory location with from the same end means that the item added last will be the
address 100. The next node with value30 is stored in the one to be removed first– last in, first out (LIFO). Stacks are
memory location with address 103 and so on. The last node
__________________
© 2023/0795 CSC/Notes 6
also called LIFO lists as they use the last in first out operands. This is known as the infix notation. This
principle. notation poses problems for more complicated
expressions. For example:

Push C C Pop
top → B → B → B
Is {
A A A
Stack Stack Stack
Infix notation requires the use of order of precedence
The main stack operations are: of operators and the use of brackets for associativity,
making it complicated and difficult for computers to
Operation Description evaluate expressions in this form. To ease evaluation
S.push(x) of arithmetic expressions, other notations are used: the
Inserts the element x to the top
or prefix and postfix notations.
of the stack S.
push(S,x) In prefix notation also called polish notation, operators
S.pop() are written before their operands. For example, the
Removes the element at the top
or expression will be written in prefix
of the stack S.
pop(S) notation as:
S.peek()/S.top() Returns the element at the top
or of the stack S without
peek(S)/top(S) removing it.
S.isEmpty() Checks if the stack S is empty. In postfix notation also called reverse polish notation
or Returns true if it is empty and (RPN), operators come after their operands. For
isEmpty(S) false otherwise. example
S.isFull() Checks if the stack S is full.
or Returns true if it is full and
isFull(S) false otherwise.
Infix Prefix Postfix
a+b+c + + abc ab + c +
Some applications of stacks are: infix to postfix conversion,
a+b*c + a * bc abc * +
evaluation of postfix expression, recursion, control of
subroutine calls, and backtracking. (a + b) * (c – d) * + ab - cd ab + cd - *

(a) Infix, Prefix and Postfix Expressions Prefix and postfix notations do not require brackets or
Arithmetic expressions are usually written in the precedence rules. Calculators use postfix notation to
form , where the operator is in between the evaluate arithmetic expressions.
__________________
© 2023/0795 CSC/Notes 7
(b) Infix to Postfix Conversion 3. 3^2 + 3 * 2 – 4
To convert from infix to prefix or postfix, priorities are 1. to postfix.
assigned to operators as follows,
Symbol Output
Stack
scanned
A A
…and the following rules are used:
+ + A
- When an operand lies between two operators, it
B + AB
associates with the operator that has higher
* +* AB
priority.
C +* ABC
- When an operand lies between operators of same ABC*
/ +/
priority, it associates with the operator on the left.
D +/ ABC*D
ABC*D/+
When converting from infix to postfix,
*top of stack is on the right
1. Scan the expression from left to right
2. If the element scanned is an operand, send it to the 2. (A + B) * (C – D) to postfix.
output
3. If the element scanned is a left bracket, push it
Symbol Output
onto stack Stack
scanned
4. If the element scanned is an operator, then
( (
- If the operator at the top of the stack has
A ( A
greater or equal priority with the operator
+ (+ A
being pushed, pop until you meet an operator
B (+ AB
of lesser priority, then push the one scanned
) AB+
- Push operator onto stack if it has higher
* * AB+
priority than the operator at the top of the
( *( AB+
stack.
5. If the element scanned is a right bracket, then C *( AB+C
- Repeatedly pop from stack and add to output – *(– AB+C
until a left bracket is found D *(– AB+CD
- Remove the left bracket. ) * AB+CD–
AB+CD–*
Examples: Convert the following infix expressions *top of stack is on the right
into postfix.
1. A + B*C/D 2. (A + B) * (C – D)
__________________
© 2023/0795 CSC/Notes 8
3. 32 + 3 * 2 – 4 to postfix. Examples: Evaluate the following postfix expressions:
1. 234*5+ –
Symbol 2. 32^32*+4
Stack Output
scanned
3 3 1. Evaluating 234*5+ –
^ ^ 3
2 ^ 32 Symbol
32^ Stack Operation
+ + scanned
3 + 32^3 2 2
* +* 32^3 3 23
2 +* 32^32 4 234
– – 32^32*+ * 2 3 * 4 = 12
4 – 32^32*+4 12 2, 12 Push result onto stack
32^32*+4– 5 2, 12,5
*top of stack is on the right. + 2 12 + 5 = 17
17 2, 17
– 2 – 15 = –15
(b) Evaluation of Postfix Expression
–15 –15 Output: –15
Arithmetic expressions written in prefix or postfix are
*top of stack is on the right
evaluated using stacks. For postfix expressions, scan
the expression from left to right taking one element at
a time. If element is an operand, push it into stack. If it Consider an empty stack S. The above evaluation
is an operator, pop first element form top of stack then can be written as follows:
pop next element from top of stack, perform operation S.push(2)
on two elements and push the result into stack. S.push(3)
When evaluating a postfix expression, S.push(4)
1. Scan the expression from left to right S.push(S.pop()*S.pop())
2. If the element scanned is an operand, push it onto S.push(5)
the stack
S.push(S.pop()+S.pop())
3. If the element scanned is an operator, pop the two
S.push(S.pop() – S.pop())
operands from the stack and perform the operation
4. Push the result of the operation onto the stack
5. At the end of the expression, the value left in the Note: The first element popped is the second
stack is the result of the evaluation. operand in the operation to be performed while
the second element popped is the first operand.

__________________
© 2023/0795 CSC/Notes 9
2. Evaluating32^32*+4– Queues
A queue is a linear list in which items are inserted at one end
Symbol (tail/rear) and removed from the other end (head/front) such
Stack Operation
scanned that the first item added to the queue is the first to be
3 3 removed. Queues are also called FIFO lists as they use the
2 32 first in first out principle.
^ 3^2 = 9
9 9 Push result onto stack Enqueue Dequeue
3 93 → →
2 932 Tail Head
* 9 3*2 = 6 (rear) (front)
6 96
+ 9 + 6 = 15 The main operations on queues are:
15 15
4 15 4 Operation Description
– 15 – 4 = 11 Q.enqueue(x)
Inserts the element x to the tail
11 11 Output: 11 or
(rear) of the queueQ.
*top of stack is on the right enqueue(Q,x)
Q.dequeue()
Removes the element at the
Questions: or
head (front) of the queueQ.
dequeue(Q)
1. Consider the following sequence of stack Q.peek()/Q.top() Returns the element at the head
operations on a stack S.
or of the queue Qwithout
push(d), push(h), pop(), push(s), pop(), pop(), peek(Q)/top(Q) removing it.
push(m). Q.isEmpty() Checks if the queue Q is
or empty. Returns true if it is
Assuming the stack is initially empty, what is the
isEmpty(Q) empty and false otherwise.
sequence of popped values, and what is the final
state of the stack? Q.isFull() Checks if the queue Q is full.
or Returns true if it is full and
2. Suppose you have a stack in which values 1 isFull(Q) false otherwise.
through 5 must be pushed onto in that order, but
an item in the stack can be popped at any time.
Give a sequence of push and pop operations such Some applications of queues are:
that the values are popped in the following order:
(a) 2, 4, 5, 3, 1 (b) 1, 3, 5, 4, 2 1. FCFS scheduling
2. I/O buffering
__________________
© 2023/0795 CSC/Notes 10
3. Print spooler  Edge: A connection between one node to another.
4. Breath First Search Traversal  Depth of a node: The number of edges from the
node to the tree’s root node.
Binary Trees
 Path: A sequence of nodes and edges connecting a
A binary tree is a special type of linked list in which each node with a descendant.
node may point to two other nodes. A binary tree can also be
 Level of a node: The level of a node is defined by
defined as a finite set of nodes that is either empty or
1 plus the depth of the node. The Root is at Level
consists of a root node and two disjoint binary trees called
1 and the children of the root node are at Level 2.
left subtree and right subtree. Binary trees are a very
efficient way of storing items that must be searched for and  Height of a node: The number of edges on the
retrieved quickly. Below is an example of a binary tree. longest downward path between that node and a
leaf.
 Height of a tree: The height of the tree’s root.

(b) Types of Binary Trees


A binary tree can be full (strictly), complete or
skewed.

 If every node in a binary tree has either 0 or two


children, then it is a full or strictly binary tree. This
means that each node is either a leaf or has exactly
(a) Binary Tree Terminologies two children.
Some terminologies used in binary trees are:
 Root: The top node in a binary tree.
 Child: A node directly connected to another node
when moving away from the Root.
 Siblings: Nodes with the same parent.
 Descendant: A node reachable by repeated
proceeding from parent to child.
 Internal node: A node with at least one child.
 External or Leafnode: A node with no children.
 Degree of a node: The number of sub-trees of a  If all the internal nodes in a binary tree have two
node. children and all the leaf nodes are at the same
__________________
© 2023/0795 CSC/Notes 11
level, then it is a perfect or full and complete
Properties of Binary Trees
binary tree.
1. The maximum number of nodes on level i of a
binary tree is 2i-1, where i ≥ 1
2. The maximum number of nodes in a binary tree
of depth k is 2k–1, where k ≥ 1
3. The number of nodes n in a full binary tree, is
at least n = 2h+1 and at most n = 2h+1–1,
where h is the height of the tree.
4. A binary tree of n elements has n-1 edges.
 If all the levels in a binary tree are completely 5. A binary tree of height h has at least h and at
filled except possibly the last and the last level is most 2h-1 elements.
strictly filled from left to right, then it is a 6. A tree consisting of only a root node has a
complete binary tree. height of 0
7. The number of internal nodes in a complete
binary tree of n nodes is n/2.

(c) Binary Tree Representation


A binary tree can be represented in two ways: using an
array (array representation) and using a linked list
(linked list representation).

Array Representation
 If the new nodes in a binary tree are added only to In the array representation of a binary tree, we use a
one side of the binary tree then it is a skewed one-dimensional array to represent the binary tree.
binary tree. Each node in the tree is stored in the array at an index
defined as follows:

Case 1: Where array referencing starts with 0.


- If node is the root, then i = 0
- If node is stored at the ith index, then
 its left child is stored at index:2*i+1
 its right child is stored at index:2*i+2
- Parent would be at index: (i–1)/2if i ≠ 0.

__________________
© 2023/0795 CSC/Notes 12
 If i = 0, then i is index of the root and root representation suffers from insertion and deletion of
has no parent. node from the middle of the tree as it requires the
movement of potentially many nodes to reflect the
Case 2: Where array referencing starts with1. change in level number of these nodes.
- If node n is the root, then i = 1
- If n is stored at ith index, then Linked List Representation
 its left child is stored at index:2*i In a linked list representation of a binary tree, every
 its right child is stored at index:2*i+1 node consists of three fields: first field for storing the
- Parent would be at index: i/2if i ≠ 1. address of the left child, second field for storing actual
 If i = 1, then i is index of the root and root data and the third field for storing the address of the
has no parent. right child. If any subtree is empty, then the pointers to
left child and right child will store a NULL value. If
Examples: the tree itself is empty, then the root pointer will store
1. Consider the binary tree above; its array a NULL value.
representation is:
LeftChild Data RightChild
17 9 15 6 5 8 10
Where LeftChild is a pointer to the left child and
2. Give the array representation of the binary tree RightChild is a pointer to the right child
below:
Example: Give the linked list representation of the
binary tree below:

Array representation:

A B C D - E F

Array representation is good for a complete binary tree


but it is wasteful for many other binary trees. The

__________________
© 2023/0795 CSC/Notes 13
Linked list representation:

Inorder Traversal
In an inorder traversal, the root of each subtree is
(d) Binary Tree Traversals visited after its left subtree has been traversed and
Tree traversal is the process of moving through a tree before the traversal of its right subtree. The steps for
in a specified order to process each of the nodes. Each traversing a binary tree in inorder are:
node is processed only once although it may be visited
- Visit the left subtree, using inorder
more than once. When describing a traversal strategy,
- Visit the root
we need not concern ourselves with what processing
- Visit the right subtree, using inorder
or computation is performed at each node, but in the
order in which the nodes are visited. There are four
An inorder traversal of the above binary tree will be:
common ways to traverse a binary tree: preorder,
D-B-A-E-C-F.
inorder, postorder and level order.
Postorder Traversal
Preorder Traversal In a postorder traversal, each root is visited only after
In a preorder traversal, each root node is visited before its left and right subtrees have been visited. The steps
its left and right subtrees are traversed. Preorder for traversing a binary tree in postorder are:
traversal is also called backtracking. The steps for
traversing a binary tree in preorder are: - Visit the left subtree, using postorder
- Visit the right subtree, using postorder
- Visit the root - Visit the root
- Visit the left subtree, using preorder
- Visit the right subtree, using preorder A postorder traversal of the above binary tree will be:
D-B-E-F-C-A
A preorder traversal of the following binary tree will
be A-B-D-C-E-F.
Level Order Traversal
In a level order traversal, the nodes are visited level by
level starting from the root, and going from left to
right.
__________________
© 2023/0795 CSC/Notes 14
A level order traversal of the above binary tree will be: - Insert the given elements in the BST one by one in the
A-B-C-D-E-F order given.
Preorder:
30-15-7-22-17-
For example, if we insert the numbers 10, 15, 7, 9, 16, and 3
27-60-45-75.
into an initially empty binary search tree, we obtain the tree
Inorder: below.
7-15-17-22-27-
30-45-60-75.

Postorder:
7-17-27-22-15-
45-27-60-30.

Level order:
30-15-60-7-22-
45-75-17-27.
Deleting a node from a BST is more complicated than
(e) Binary Search Trees
inserting a node or searching for a node. To delete a node,
A binary search tree (BST) or ordered binary tree is a there are three possible cases to consider: deleting anode
type of binary tree where the nodes are arranged in with no child, deleting a node with one child and deleting a
order such that for each node, all elements in its left node with two children.
subtree are less than the node, and all the elements in
Consider the following BST.
its right subtree are greater than or equal to the node. If
a node contains a value n, then every node in its left
sub-tree contains a value less than n, and every node in
its right sub-tree contains a value greater than or equal
to n.

Case 1: To delete a node with no child (a leaf node), we


simply remove the node from the tree. The pointer pointing
to the node, now points to null.
Deleting node 4 from the BST above, we obtain the
Inorder to construct a binary search tree for elements given following BST.
in sequence,
- Always consider the first element as the root node
__________________
© 2023/0795 CSC/Notes 15
Deleting the root from our BST above, we get can replace it
with node 2(inorder predecessor) or node 4 (inorder
successor). Replacing with the inorder successor, we get:

Case 2: To delete a node with one child, we remove the node


and replace it with its child. We link the node’s parent with
its child. Deleting node 2 from the BST above, we get:

(f) Binary Expression Trees


A binary expression tree is a specific kind of binary
tree used to represent expressions. Two common types
of expressions that a binary expression tree can
represent are algebraic and Boolean expressions.
These trees can represent expressions that contain both
unary and binary operators. In a binary expression
tree, leaf nodes represent operands (constants or
Case 3: To delete a node with two children, we replace the
variables) while non-leaf nodes represent operators.
node with its inorder predecessor or successor and then
delete the inorder predecessor or successor, depending on
which one we choose.
- A node’s inorder predecessor is its left subtree’s
rightmost child. It is the node with maximum value in
the targeted node’s left subtree.
- A node’s inorder successor is its right subtree’s left-most
child. It is the node with minimum value in the targeted
node’s right subtree.

In either case, this node will have zero or one child and can To evaluate the expression represented by the tree we
be deleted using either case 1 or case 2 above, depending on use preorder, inorder or postorder traversals.
whether they have a child or not. Preorder traversal yields:
Inorder traversal yields:
Postorder traversal yields:
__________________
© 2023/0795 CSC/Notes 16
Hash Tables location in the table. The key is inserted into this
A hash table is an array in which data is stored at specific location.
locations designated by a hash function. A hash function is a Using the hash function h(k) = k mod 7, insert in
calculation that transforms the value of a record key into an the order given, the keys 22, 11, 15, 6, 23
index that corresponds to a location for storing the record.
A has table stores elements in key-value pairs where: Key Hashed value
- Key is a unique integer that is used for indexing the
22 22 % 7 = 1
values.
- Value is that data associated with keys. 11 11 % 7 = 4
15 15 % 7 = 1
Suppose we want to store the keys: 22, 13, 11, and 24 in has 6 6 % 7 = 0
table of size 7, using the hash function h(key) = key modulo 23 23 % 7 = 2
7.
Key Hashed value
22 22 % 7 = 1
13 13 % 7 = 6
11 11 % 7 = 4
24 24 % 7 = 3 (b) Separate Chaining
42 42 % 7 = 0 In separate chaining, each element of the hash table is
a linked list. Keys that have the same hashed value are
stored in the same list.

Using the hash function h(k) = k mod 7, insert in


the order given, the keys 22, 11, 20, 32, 8, 25, and32.

With hash tables, there always exists the possibility that two Key Hashed value
data elements will hash to the same integer value. This 22 22 % 7 = 1
situation is known as a collision. Two methods to solve
11 11 % 7 = 4
collisions are linear probing and separate chaining.
20 20 % 7 = 6

(a) Linear Probing 32 32 % 7 = 4


In linear probing, when a key hashes to a location that 8 8 % 7 = 1
is already occupied, we find another location by 25 25 % 7 = 4
sequentially searching for the next available or empty
__________________
© 2023/0795 CSC/Notes 17
Homogeneous and Heterogeneous
Homogeneous data structures hold elements of the same data
type. This means that all the elements that are held are of the
same data type. Example: arrays and linked lists.
On the other hand, heterogeneous data structures hold
elements of different data types. Example: records.

Static and Dynamic


Static data structures have a fixed-size of elements during
execution. This means that memory allocated to hold the
data items is fixed in size and space cannot be freed up when
the program is running. Examples are arrays.
9.1.4. Data Structures
Dynamic data structures can expand or shrink during
A data structure is a data organization and storage program execution depending on whether elements are
format that enables efficient access and modification. added to or deleted from the data structure respectively.
Any data structure is designed to arrange data to suit a Their size is not fixed at execution. Examples are linked lists
specific purpose such that the data can be accessed and and trees.
worked with in appropriate ways.
Finding the best data structure when solving a problem is an Linear and Nonlinear
important part of programming. The choice of a particular Linear data structures have their elements stored in a list or
data structure when solving a given problem can be in a straight sequence. Examples are arrays, linked lists,
determined by the following factors: stacks and queues.
 The data structure’s ability to meet requirements. Nonlinear data structures are structures in which elements
 The basic operations supported by the data structure may be arranged in hierarchical manner. Examples are trees
 The resource constraints or efficiency of the data and graphs.
structure (that is, how much space does the data
structure occupy and what are the runtimes of the In general, data structures are used to implement (or build)
operations in its interface) the physical forms of abstract data types. This can be
translated into a variety of applications, such as displaying a
Data structures can be classified in different ways, based on relational database as a binary tree.
whether they are: homogeneous or heterogeneous, static or
dynamic, linear or nonlinear.

__________________
© 2023/0795 CSC/Notes 18
9.2. Algorithm Design means that each step must have one and only one
meaning. It must be interpreted in only one way.
Algorithmic problem solving actually comes in two phases: derivation
of an algorithm that solves the problem, and conversion of the
algorithm into a computer program. To derive an algorithm to solve a 3. An algorithm must be finite
problem the following steps are followed: The ultimate purpose of an algorithm is to solve a
problem. If the algorithm does not stop when executed,
we will not be able to get any result from it. Therefore,
o Define/Understand the Problem: State the problem you are trying
an algorithm must contain a finite number of steps in its
to solve in clear and concise terms. It involves answering the
execution.
question, “What will the algorithm do?”
4. An algorithm must be general
o Analyze the Problem: Identify the problem inputs (the data needed
This means that it must solve every instance of the
to solve the problem), outputs (what the algorithm will produce as
problem. For example, an algorithm that computes the
result), and additional requirements or constraints on the solution.
area of a rectangle should work on all possible
dimensions of the rectangle.
o Develop the Algorithm: Describe the steps needed to convert the
inputs to produce the outputs. It involves writing the step-by-step
9.2.2. Representation of Algorithms
procedure for solving the problem.
Algorithms can be written as a set of numbered steps to
o Test the Algorithm: Verify that the algorithm solves the problem as follow such as a cooking recipe or assembly instructions;
intended. Choose data sets and verify that the algorithm works. however, in computing they are presented as pseudo code or
flowcharts.
9.2.1. Characteristics of an Algorithm
Pseudo code
What makes an algorithm an algorithm? Some essential
characteristics of an algorithm are correctness, unambiguity, Pseudo code is a way of writing out algorithms using
finiteness and generality. formatted English or code-like statements. There is no
standard convention for writing pseudo code; each author
may have their own style, as long as clarity is ensured.
1. An algorithm must be correct
An algorithm must provide the correct results when A keyword is a word that is reserved in a programming
provided with valid or correct inputs to the problem. language because the word has a special meaning. Every
programming language has its keywords. In pseudo code
2. An algorithm must be unambiguous keywords are used to indicate common input-output and
Each step in an algorithm should be clearly and precisely processing operations. Below are some examples of
defined and there should be no ambiguity. No ambiguity keywords which are used in pseudo code.

__________________
© 2023/0795 CSC/Notes 19
Keyword Meaning Flowchart

START/BEGIN Indicate the beginning A flowchart is a graphical representation of an algorithm. In


… and the end of the a flowchart, symbols represent operations and the arrows
STOP/END algorithm. linking them represent the order of execution of instructions
Indicates an input (also called flow of control or logic of the algorithm). The
statement. For example: following are common symbols used in flowcharting and
READ/GET/ their meanings.
- GET (number)
INPUT
- READ (Name)
- INPUT Radius
Symbol Meaning
Indicates an output
statement. For example: Terminal: Indicates the beginning and
PRINT/DISPLAY/ the end of the algorithm.
OUTPUT - PRINT(Sum)
- DISPLAY(Area) Input/Output: Indicates input or output
- OUTPUT "Hello of data. For example,
World!"
- GET a number
Used to initialize values.
- PRINT result
For example:
SET/INIT - SET Sum to 0 Process: Indicates any type of internal
- INIT Counter to 1 operation. For example,
- SET PI = 3.14 - Sum ← Sum + i
COMPUTE/ Used to determine the - Set Counter to 1
CALCULATE result of an expression. - Increment Counter by 1
IF…THEN…ELSE…ENDIF Selection control Decision/Branch: Indicates a conditional
CASEWHERE…ENDCASE statements statement that can evaluate to
WHILE…DO…ENDWHILE Repetition control True/False or Yes/No.
FOR…TO…DO…NEXT statements - If A is less than B Then
REPEAT…UNTIL - While Counter <= Num Do
FUNCTION…
ENDFUNCTION Connector: Connects sections of the
PROCEDURE Subroutines flowchart allowing the flowchart to be
… drawn without intersecting lines.
ENDPROCEDURE Subprogram: Indicates a call to a
subroutine.
Flow line: Indicates the direction of the
progression of the algorithm.

__________________
© 2023/0795 CSC/Notes 20
9.2.3. Identifiers, Variables and Constants  A variable is a data item whose value can change during
execution of the algorithm or program.
When writing an algorithm, we need to keep track of the
data values the algorithm will manipulate. Each data value is
given a name that will help us remember what it does. This  A constant is a data item whose value cannot change
name is called an identifier. Identifiers should be clear and during execution of the algorithm or program.
indicate what they will be holding. For example, Number,
Sum, Average and Counter. 9.2.4 Control Structures
The values of some data items may change during execution The order of execution of steps in an algorithm is determined
of the algorithm while others remain fixed. Any data item by input data and control structures. A control structure is a
whose value can change during execution is called a variable statement that determines the order of execution of other
while any data item whose value cannot change during statements in an algorithm. There are three basic control
execution is called a constant. Technically, variables and structures: sequence, where one statement simply follows
constants are storage locations that have been given names. another; selection, where control flow depends on which
When a value is assigned to a variable or constant, that value criteria are met; and iteration, where an action is repeated
is kept in the memory location that corresponds to that until some condition occurs.
variable or constant.
In general, variables are written with no spaces and in Sequence Control Structure
lowercase. They can be written with an underscore A sequence control structure is the construct where
separating words, which is known as snake case or, words instructions are executed one after the other in the order they
can be joined with each word starting with a capital letter, are given. The execution of instructions in an algorithm by
known as camel case. Constants are written in uppercase, default is sequential.
using snake case.
The following statements are executed in sequential fashion.
Snake Case Camel Case
player_name playerName Begin
Get A
high_score highScore
Get B
date_of_birth dateOfBirth Average ← (A+B)/2
VAT_RATE Print(Average)
End
 An identifier is a unique name or label given to a data
item, which distinctly identifies the data item. Identifiers
are used for the naming of variables, constants, records
and functions.

__________________
© 2023/0795 CSC/Notes 21
In a flowchart, sequence is expressed as: In a flowchart, a single alternative if is expressed as:

Statement 1
No Is condition Yes
Statement 2 true?

Statement

Statement n

Below is an algorithm that gets two numbers (dividend


Selection Control Structures and divisor), computes and displays the quotient if the
divisor is different from zero.
A selection control structure is the construct where one or
more statements can be executed or skipped depending on
Begin
whether a condition evaluates to true or false.
Get Dividend
There are three selection structures: If...Then, If…Else and Get Divisor
Case. If Divisor ≠ 0 Then
Quotient ← Dividend/Divisor
(a) If…Then (Single Alternative If) Print Quotient
End
Syntax: A single alternative If statement has the
form:
If condition Then Exercise: Express the algorithm above as a flowchart.
Statement(s)
EndIf
(b) If…Else (Dual Alternative If)
Semantics: Syntax: A dual alternative If statement has the form:
 First, the condition is evaluated; condition is an
If condition Then
expression of type Boolean. Boolean means that it
Statement1
can evaluate to either true or false. Else
 If condition evaluates to true, the statement or Statement2
statements enclosed within the keywords Then and EndIf
EndIf are executed. If it evaluates to false, noting
is done.

__________________
© 2023/0795 CSC/Notes 22
Semantics: (c) Case (Multi-way selection)
 If condition evaluates to true, Statement1is Syntax: A multi-way selection structure has the form:
executed.Statement1 can be a single statement or it
Casewhere expression is
can be two or more statements.
Choice_1 : Statement1
 If condition evaluates to false, Statement2is Choice_2 : Statement2
executed instead. Like Statement1, Statement2 can ...
be a single statement or it can be two or more Choice_n :Statement n
statements. Otherwise : default statement
EndCase
Begin
Get Mark
If Mark>=10 Then Semantics:
Print("Passed")  First, the expression is evaluated. It can evaluate to
Else any of the choices given in the case structure or not.
Print("Failed")  If it evaluates to Choice_1, Statement1 is executed.
EndIf
If it evaluates to Choice_2, Statement2 is executed
End
and so on.The path taken is determined by the
selection of the choice that is true.Each statement
can be a single statement or a group of statements.
In a flowchart, a dual alternative if can be expressed as  If it does not evaluate to any of the choices given,
follows: the default statement is executed.

Begin
Is Get Number1
Yes No
condition Get Number2
true? Get Operator
Statement1 Statement2
Casewhere Operator is
+: Result ← Number1 + Number2
–: Result ← Number1 – Number2
*: Result ← Number1 * Number2
/: If Number2 ≠ 0 Then
Result ← Number1/Number2
Otherwise: Print "Error!"
EndCase
Print Result
End

__________________
© 2023/0795 CSC/Notes 23
In a flowchart, multi-way selection is expressed as: (a) While Loop
Syntax: A while loop has the form:
While condition Do
Statement(s)
Condition
EndWhile

Semantics:
Choice1 Choice2 Otherwise  First, the condition is evaluated.
Statement1 Statement2 Default statement  If it is true, the statements in the body of the
loop are executed and the condition is evaluated
again, continuing in this way until the condition
becomes false.
Repetition Control Structures  If the condition is false, the body of the loop is not
executed and the statement immediately following
A repetition control structure is the construct where one or
the while loop is executed.
more instructions can be executed repeatedly depending on
whether a condition evaluates to true or false. One way to
Hence, the body of the loop is executed as long as
obtain the repetition of steps in an algorithm is the use of
loop statements (iterative statements). A loop is a sequence the condition stays true. As soon as it becomes
of instructions that is repeated until a certain condition is false, we exit the loop and continue with the
met. Each pass through a loop is known as iteration. There statement that comes immediately after the word
are three types of loops namely while, for, and repeat (or do- EndWhile.
while) loops.
An essential feature of repetition is that each loop has a Example 1: An algorithm to print "Hello World!" 10
termination condition to stop the repetition, or the obvious times.
outcome is that the loop never completes execution (an loop condition
infinite loop). The termination condition can be checked or
tested at the beginning or at the end of the loop. When the
Begin
condition is tested at the beginning, the loop is known as a
i ← 1
pre-test loop. Examples of pre-test loops are the while loop Whilei <= 10Do
and the for loop. When the condition is tested at the end of loopbody Print("Hello World!")
the loop, the loop is known as a post-test loop. Examples of i ← i + 1
post-test loops are the repeat loop (or do-while loop). EndWhile
End

__________________
© 2023/0795 CSC/Notes 24
Example 2: Algorithm to print the sum of n positive, (b) For Loop
non-zero integers entered by the user. To stop the Syntax: A for loop has the form:
entering, the user enters 0.
For counter ← start To end Do/[Step inc]
begin Statement(s)
get(num) Next counter
sum ← 0
while num ≠ 0 do - counter: a numeric variable used to control the
sum ← sum + num loop.
get(num) - start: the initial value of counter.
endwhile
- end: the final value of counter.
print(sum)
end - inc: the amount to add to counter each time
the loop executes. If it is not specified, increment
defaults to 1.
Every while loop will always contain three main - Statement(s: the body of the loop. It could be
elements: one statement or more statements.
 Priming: initialize the loop control variable.
 Testing: test against some known condition. Semantics:
 Updating: update the variable that is tested  First, the variable counter is initialized to
start.
Priming Testing  If the value of counter is less than end(final
value), the body of the loop is executed.
begin
i ← 1  Counter is incremented by 1 (by default) or by
while i <= 10 do the amount specified as increment and then
print("Hello World!") checked again. If it is less than end, the body
i ← i + 1 Updating of the loop is executed again, continuing in this
endwhile
way until counter becomes greater than end.
end
 If counter is greater than end, the loop is not
executed and the statement immediately
following the for loop is executed.

Hence, the body of the loop is executed for every


value of counter that is less than or equal to the
__________________
© 2023/0795 CSC/Notes 25
final value (end) specified in the loop. As soon as begin
counter becomes greater than the final value, we get(LB,UB)
exit the loop and continue with the statement that sum ← 0
comes immediately after Next. for i ← LB to UB do
if i mod 2 = 0 then
Example 1: Algorithm to print "Hello World!" 10 sum ← sum + i
endif
times.
next i
print(sum)
begin
end
for i ← 1 to 10 do
print("Hello World!")
next i
end (c) Repeat Loop
Syntax: A repeat loop has the form:

Example 2: Algorithm to print the first five powers of Repeat


2. Statement(s)
Until condition
Begin
powOf2 ← 1 Semantics:
For i ← 0 To 4 Do
 First, the body of the loop is executed.
Print("2ˆi = ", powOf2)
powOf2 ← powOf2 * 2  Then, the condition is evaluated, and if it is
Next i false, the loop is executed again, continuing in
End this way until the condition becomes true.

Example 3: An algorithm to calculate and print Hence, the body of the loop is executed as long as
the sum of all even numbers in a given range of the condition stays false. As soon as it becomes
true, we exit the loop and continue with the
numbers.
statement that comes immediately after Until.

(d) Do-while Loop


Syntax: A do-while loop has the form:
Do
Statement(s)
While condition
__________________
© 2023/0795 CSC/Notes 26
Semantics: for count ← 1 to 5 do
 First, the body of the loop is executed. print(count)
 Then, the condition is evaluated, and if it is next count
true, the loop is executed again, continuing in
this way until the condition becomes false. Here is a similar example that executes 6 times:

Hence, the body of the loop is executed as long as for count ← 0 to 5 do


print(count)
the condition stays true. As soon as it becomes
next count
false, we exit the loop and continue with the
statement that comes immediately after While.
The benefit of a for loop is that the variable that is
used to control the loop increments automatically by 1
(e) Definite and Indefinite Loops
except it is explicitly modified.
We distinguish two types of loops, definite and
indefinite, which differ in the way in which the Here is an example of a while loop that repeats 4
number of iterations is determined. That is, they times.
differ in the way in which we can determine the
number of times the body of the loop will execute. count ← 1
while count < 5 do
print(count)
Definite Loops count ← count + 1
With definite loops, also called count-controlled endwhile
(counting) loops, the body of the loop repeats a
specific number of times. This means that the number
of iterations is known before we start the execution of If you write the same instructions using a do…while
the loop. Definite loops use a counter variable to loop, which checks the condition at the end of each
control the number of times the loop iterates. The iteration, the output will be the following 5 numbers:
counter variable is set to a particular initial value and
count ← 1
incremented at the end of each iteration until it passes
do
a particular final value. Definite loops can be print(count)
implemented using any of the while, repeat and do- count ← count + 1
while loops but they are mostly implemented using while count <= 5
the for loop.
Here is an example of a for loop that repeats 5 times. Note that the above two loops replicate the function of
a for loop but the variable that is used to control the
__________________
© 2023/0795 CSC/Notes 27
loop in this case count) has to be explicitly Note that the condition has changed from age <
incremented in the code (count ← count + 1). 18 to age >= 18. This is because the loop body
will execute until the condition age >= 18
Indefinite Loops evaluates to true. In other words, the loop
With indefinite loops, also called condition-controlled
repeats while the condition evaluates to false,
(conditional) loops, the body of the loop repeats until a
instead of while it evaluates to true.
certain condition is met, instead of a fixed number of
times. This means that the number of iterations is not
9.2.5. Subroutines
known before we start to execute the loop, but depends
on when a certain condition becomes true (and this Programs can be divided into blocks of instructions that each
depends on what happens in the body of the loop). perform some specific task on different data values. These
Condition-controlled loops are implemented using are known as subroutines or subprograms. A subroutine is a
while and repeat(or do-while) loops. named block of code which performs a specific task within a
program. This block of code can be used wherever that
Here is an example of a while loop that keeps getting particular task should be performed. Different programming
an age from the user until the age is greater than or languages have different names for subroutine like method,
equal to 18. The loop will repeat for as long as the user function, or procedure.
enters an age that is lower than 18. In other words, it
will repeat while the condition age<18 evaluates to Functions and Procedures
true. A subroutine can be classified as a function or a procedure.
Not all programming languages differentiate between
get(age)
functions and procedures however, in a theoretical context, a
while age < 18 do
print("enter an acceptable age.") function returns a value(or more values) to its caller while a
get(age) procedure does not return any value.
endwhile
Example 1: A function to compute the factorial of a number.
We can use a repeat loop to write a similar function factorial(n)≡
algorithm. A repeat loop will first execute the fact ← 1
instructions inside the iteration block and then for i ← 1 to n do
check the condition. fact ← fact * i
next i
repeat return fact
print("enter an acceptable age.") endfunction
get(age)
until age >= 18

__________________
© 2023/0795 CSC/Notes 28
Example 2: A function that computes the greatest common Printing the return value would simply make it appear on the
divisor of two numbers. screen.

function gcd(m,n)≡ Calling a Subroutine


while n > 0 do
r ← m mod n
A subroutine is called or invoked by writing the subroutine
m ← n name in an instruction and passing parameters to it. The
n ← r instruction that invokes a subroutine is known as a CALL
endwhile instruction.
return m A CALL instruction for a procedure has the form:
endfunction
procedure(arg1,arg2,…)

Example 3: A procedure to swap two variables. procedure swap(x,y)≡


t← x
procedure swap(x,y)≡ x← y
t← x y← t
x← y endprocedure
y← t
endprocedure begin
get num1,num2
swap(num1,num2)
Example 4: A procedure to display menu items and then get print num1,num2
the user’s choice. end

procedure menu()≡ The line


print "1. add" swap(num1,num2)
print "2. subtract"
print "3. multiply" is a CALL instruction. It calls the procedure swap, passing to
print "4. divide" it the variables num1 and num2. The call transfers execution
get choice to the procedure swap, which swaps the values passed to it.
endprocedure
A function can be called or invoked in different ways:

There is a difference between returning a value and  By assigning the return value to a variable.
outputting a return value (i.e. with a print statement). A
variable ← function(arg1,arg2,…)
return value from a function can be assigned to a variable
and used in further calculations outside of the function.
__________________
© 2023/0795 CSC/Notes 29
function square(n)≡ function cube(n)≡
squared ← n * n cubed ← n * square(n)
return squared return cubed
endfunction endfunction

begin begin
get(num) get num
result ← square(num) print("result = ", cube(num))
print(result) end
end
Parameter Passing
A subroutine may be written so that it expects to obtain one
The line
or more data values from the caller (main program or another
result ← square(num) subroutine). These data values are called its parameters.
calls the function square, passing to it the variable num. The Parameter passing is the exchange of data between a calling
function square computes the square of num and the program (caller) and a subroutine. When a caller program
computed value is returned to the caller and stored in the invokes a subroutine, it could pass to it zero, one or more
variable result. data values as parameters.

 By using the return value directly in a calculation. (a) Formal and Actual Parameters
Parameters may be actual or formal.
function square(n)≡ - Actual parameters are variables or values which
squared ← n * n
are passed into a subroutine when the subroutine is
return squared
invoked or called. Actual parameters are often
endfunction
called arguments.
begin
- Formal parameters are variables which are used in
get radius a subroutine definition to stand for the values that
area← 3.14 * square(radius) are passed into the subroutine by a caller.
print "area = ",area
end

 By using the return value directly as an argument in


another subroutine call.

__________________
© 2023/0795 CSC/Notes 30
Input: num1 = 4, num2 = 5
Function square(n)≡
squared ← n * n Call swap: swap(num1,num2)
return squared x = 4
EndFunction y = 5
After swap: x = 5, y = 4
Begin
Get(num) Print num1: prints 4
result ← square(num) Print num2: prints 5
Print(result)
End The variables num1and num2 are actual parameters
and the variables x and y are formal parameters. The
In the above algorithm, n is a formal parameter and value of num1 is copied into x and the value of num2
num is an actual parameter. is copied into y. The changes made on variables x and
y do not affect the values of num1 and num2 because
(b) Passing Parameters by Value the parameters were passed by value.
In pass-by-value, the values of the actual parameters
are copied into the formal parameters and these formal (c) Passing Parameters by Reference
parameters are used in the called subroutine. The In pass-by-reference, the address of the actual
changes made on the formal parameters do not affect parameter is passed into the formal parameter.
the values of the actual parameters. This means that Changes made inside the subroutine are reflected in
when the execution is returned to the caller, the values the actual parameter.
in the actual parameters remain the same.
procedure swap(ptr1,ptr2)≡
procedure swap(x,y)≡ temp ← *ptr1
t← x *ptr1 ← *ptr2
x← y *ptr2 ← temp
y← t endprocedure
endprocedure
begin
begin get(num1,num2)
get(num1,num2) swap(&num1,&num2)
swap(num1,num2) print(num1)
print(num1) print(num2)
print(num2) end
end

__________________
© 2023/0795 CSC/Notes 31
ptr1 and ptr2 are pointers. Pointers hold addresses. When we invoke function A, which contains a call to
This means that the parameters to the procedure swap function B, then its processing will not be completed until
are addresses. The character & (ampersand) is the function B has completed its execution and retuned.
address operator; when written in front of a variable, it Similarly, function B will not be completed until function C
returns the memory address of the variable. This has completed its execution and returned. Function A will
means that the arguments that are passed to the only be completed after function B is completed and
procedure swap when it is called are the addresses of function B will only be completed after function C is
the variables num1 and num2. *ptr1 returns the value completed. Therefore, function A is first to be started and
in the location whose address is held in ptr1. By last to be completed. This matches the first in last out
passing the addresses of num1 and num2, changes behavior and can easily be handled using a stack
made inside the procedure swap will affect the values Consider addrA, addrB and addrC to be the addresses of the
inside num1 and num2. statements to which control is returned after completing the
functions A, B and C respectively.
Processing Function Calls
Implementation of subroutine calls and returns use a CALL
stack, a special case of the stack data structure. Each addrC
subroutine call creates a new entry, called a stack frame, at addrB addrB
the top of the stack; when the subroutine returns, its stack addrA addrA addrA
frame is deleted from the stack and its space may be used for A() is B() is C() is
other subroutine calls. Each stack frame contains the private called called called
data of the corresponding call, which typically includes the
subroutine’s parameters and local (internal) variables, and The return addresses appear in the stack in reverse order in
the return address. which the functions were called. After each function is
Suppose we have a program containing three functions: A(), completed, the pop operation is performed, and execution
B(), and C(). Function A invokes function B, which continues at the address removed from the stack. Thus the
invokes function C. program that calls several functions in succession can be
handled optimally by the stack data structure. Control returns
main() A() B() C() to each function at a correct place, which is the reverse order
{ { { {
of the calling sequence.
……………… ……………… ……………… ………………
……………… ……………… ……………… ………………
A() B() C() ………………
addrA addrB addrC ………………
……………… ……………… ……………… ………………
} } } }

__________________
© 2023/0795 CSC/Notes 32
Advantages of Subroutines new problem looks like the original problem, the method
launches a recursive call to work on the smaller problem. For
 It reduces duplicate code within a program, thereby
recursion to terminate, each time the recursive routine calls
reducing the size of the program
itself with a slightly simpler version of the original problem,
 It enables reuse of code in a program or across
programs the sequence of smaller and smaller problems must converge
on the base case. When the method recognizes the base case,
 It makes it easier to maintain a program.
the result is returned to the previous method call and a
 It helps to divide a large programming task amongst
various programmers, which saves time and increases sequence of returns ensures all the way up the line until the
quality original call of the method eventually returns the final result.
Some examples of recursive algorithms are factorial
function, greatest common divisor, summation function, and
9.2.6. Recursion Fibonacci series.
If a subroutine calls a subroutine, then that is called
subroutine nesting. Conceptually, subroutine nesting can be Factorial Function
carried out to any depth. The first subroutine to complete The factorial function is defined as follows:
will be the one that was called last, causing control to return 0! = 1
to the one that called it. If nesting involves a subroutine 1! = 1
calling itself, then we call that recursion.
2! = 2*1
Recursion is the ability for a routine to call itself. It is a
3! = 3*2*1
problem-solving technique in which the solution to a
...
problem is defined by applying the same solution to smaller
instances of the problem. n! = n*(n-1)*(n-2)*...*3*2*1*0
Recursion is a very powerful technique that can be used By studying the above equations closely, we see that the
when programming an algorithm in which there are a factorial of any number can be calculated by multiplying
variable number of iterations. Recursive routines have two the number by the factorial of the preceding number. We can
important features: then rewrite the general formula for calculating factorial as
 a recursive routine calls itself (general case) follows:
 it must have a terminating condition (base case)
n! = n*(n-1)!

If a recursive routine is called with a base case, the routine


returns a result. If it is called with a more complex problem, Factorial is defined recursively as follows:
the routine divides the problem into two or more conceptual
pieces: a piece that the method knows how to do and a 1 if n <= 0
n!=
slightly smaller version of the original problem. Because this n*(n-1)! if n > 0
__________________
© 2023/0795 CSC/Notes 33
function fact(n)≡ function gcd(m,n)≡
if(n = 0)then if(n = 0)then
return 1 return m
else else
return n*fact(n-1) return gcd(n,m mod n)
endif endif
end end

Fibonacci Sequence
The line
The Fibonacci sequence is the series of numbers:
return 1
0,1,1,2,3,5,8,13,21,34,…
is the base case. Every recursive problem must have at least
one base case which can be solved without recursion. The next number in the sequence is found by adding the two
numbers before it.
The line Recursively, the Fibonacci sequence can be defined as:
return n*fact(n-1)
0 if n=0
is the recursive call (or general case). The recursive call must
always make progress towards the base case, in this case, n, fib(n)= 1 if n=1
n-1, n-2, n-3, …, 2, 1, 0.
Notice that in the recursive call, the name of the called fib(n-1) + fib(n-2) if n>1
function is fact, the same name as the function that made the
call. function fib(n)≡
if(n = 0)then
Greatest Common Divisor return0
The greatest common divisor of two integers which are not else
if n = 1 then
all zero is the largest positive integer that divides each of the
return 1
integers.
else
Recursively, gcd can be defined as follows:
return fib(n-1) + fib(n-2)
endif
m if n=0
endif
gcd(m,n)=
gcd(n,m mod n) if n>0 end

__________________
© 2023/0795 CSC/Notes 34
Iteration vs Recursion are broken into smaller sub-problems, continuing until
each sub-problem can be solved in a few steps.
Both iteration and recursion are based on a control
structure: Iteration uses a repetition structure;  Top-down approach starts with high-level design and
recursion uses a selection structure. ends with the low-level implementation.
Both iteration and recursion involve repetition:  Top-down design is helpful in software development,
Iteration explicitly uses a repetition structure; project management and other fields where complex
recursion achieves repetition through repeated tasks must be decomposed into smaller, more
method calls. manageable parts.
Iteration and recursion each involve a termination  It is mainly used by structured programming languages
test: Iteration terminates when the loop-continuation such as C, COBOL and Fortran.
condition fails; recursion terminates when a base
case is recognized.
Divide-and-Conquer
Iteration and recursion can occur infinitely: An
infinite loop occurs with iteration if the loop-  A divide-and-conquer algorithm is a strategy for solving
continuation test never becomes false; infinite a large problem by:
recursion occurs if the recursion step does not
reduce the problem in a manner that converges on - Divide: breaking the problem into sub-problems of
the base case. the same type.
Recursion repeatedly invokes the mechanism, and - Conquer: solving each sub-problem recursively
consequently the overhead, of method calls. This - Combine: appropriately combining the solutions to
can be expensive in both processor time and the sub-problems
memory space.
 To use the divide-and-conquer algorithm, recursion is
used.
9.2.7. Algorithm Design Techniques  Binary search and quicksort are two divide and conquer
Different problems require different algorithmic approaches. algorithms.
Algorithm design techniques help you identify the most  Divide-and-conquer algorithms use top-down approach
suitable method for a specific problem. By understanding
various techniques you can select the most appropriate
approach for a given problem ensuring optimal results. Brute-Force Algorithms
 A brute-force algorithm solves a problem through
Top-down Design exhaustion: it goes through all possible choices until a
solution is found.
 Top-down design is the process of designing a solution
to a problem by systematically breaking the problem  The beauty of brute-force method is that it is
into smaller, more manageable parts. The problem is straightforward and if a solution to a problem exists, you
broken down into smaller sub-problems, which in turn are guaranteed to find it.
__________________
© 2023/0795 CSC/Notes 35
 For example: imagine that you have a small padlock that Linear Search
requires a four digit combination to open. If you forget Linear search is a very basic and simple search algorithm. In
your combination and do not want to destroy the linear search, we compare the element sought with the
padlock, a brute force solution to the problem would be elements in the array starting from the first, till the desired
to try different four digit combinations until you get the element is found or till we get to the end of the array. When
right combination. You can try the combinations from the element is matched successfully, we return the index of
0000 to 9999. the element in the array, else we return -1.
 Linear search is a brute force search.
function linearsearch(a,item)≡
i← 0
Bottom-up Design while i <sizeof(a) do
 Bottom-up design is a design process in which the if a[i] = item then
individual parts of a system are specified in detail. return i
endif
 The parts are linked to form larger components which in
i← i + 1
turn are linked until a complete system is formed.
endwhile
 Object-oriented languages such as C++, Java and Python return -1
use a bottom-up approach where each object is identified endfunction
first.

Search for the element 12 in the array A given below.


9.3. Searching and Sorting
Searching and sorting are two of the operations performed on some [0] [1] [2] [3] [4] [5]
data structures such as arrays and lists. While searching allows us to
A = 65 10 32 12 55 99
iterate over the data structure’s elements to retrieve some data, sorting
allows us to put the data structure’s elements in order. Searching and
sorting algorithms are different for every data structure. Here, our
Step 1: Compare 12 with first element 65.
focus is on searching and sorting for arrays.

[0] [1] [2] [3] [4] [5]


9.3.1. Search Algorithms
65 10 32 12 55 99
Searching is the algorithmic process of locating an element
in a list of pre-stored elements. Any search is said to be 12
successful or unsuccessful depending upon whether the
element is found or not. Some of the standard search Both don’t match, so move to next element.
algorithms are linear (sequential) search and binary search.

__________________
© 2023/0795 CSC/Notes 36
Step 2: Compare 12 with second element 10 Binary Search
[0] [1] [2] [3] [4] [5] Binary search is a fast search algorithm that works on the
65 10 32 12 55 99 principle of divide and conquer. Binary search is useful
when there is a large number of elements in an array and
12 they are sorted. So, a necessary condition for binary search
Both do not match, so move to next element. to work properly is that the list or array should be sorted.
Binary search works as follows:
Step 3: Compare 12 with third element 32. - Compare the search element with the element in the
middle of the array. If they match, then the element has
[0] [1] [2] [3] [4] [5] been found. Return the index.
99 - If the search element is greater than the middle element,
65 10 32 12 55
then continue the search in the right sub-list of the
12 middle element.
Both don’t match, so move to next element. - If the search item is smaller than the middle element,
then continue the search in the left sub-list of the middle
Step 4: Compare 12 with fourth element 12. element.
- Repeat the process until the element is found or the size
[0] [1] [2] [3] [4] [5] of the sub-list reduces to zero.

65 10 32 12 55 99
function binarysearch(a[],item)≡
12
first ← 0
Both match, so we stop the search and return index last ← sizeof(a)-1
3, where the element was found. while first <= last do
middle ← (first + last) div 2
Features of Linear Search if a[middle] = item then
return middle
1. It is suited for unordered or unsorted small lists
else
of elements
if(a[middle] < item)then
2. It has a time complexity of O(n), which means first ← middle + 1
that the time is linearly dependent on the else
number of elements, which is not bad, but not
last ← middle – 1
that good too.
endif
3. It has a very simple implementation endif
endwhile
return -1
endfunction

__________________
© 2023/0795 CSC/Notes 37
Search for the element 12 in the sorted array A given below. Both match, so we stop the search and return index
[5] 1, where the element was found.
[0] [1] [2] [3] [4]
A = 10 12 32 55 65 99
Features of Binary Search
Step 1: Compare 12 with middle element 32 1. It is great to search through large sorted arrays
middle = (0+5) div 2 = 2 2. It has a time complexity of O(log n), which is a
A[middle] = A[2] = 32 very good time complexity.
3. It has a simple implementation
[0] [1] [2] [3] [4] [5]

10 12 32 55 65 99
9.3.2. Sorting
12
Sorting is the algorithmic process of rearranging the
Both do not match, so continue search in left sub-list
elements of a list in ascending or descending order. Efficient
since 12 < 32.
sorting is important to optimizing the use of other algorithms
that require sorted lists to work correctly and for producing
Step2: Compare 12 with middle element
human-readable input. There are lots of useful sorting
middle = (0+1) div 2 = 0 algorithms including bubble sort, insertion sort, selection
A[0] = 10 sort, quick sort, merge sort and heap sort.
[0] [1] [2] [3] [4] [5]
Bubble Sort
10 12
Bubble sort is a simple sorting algorithm that repeatedly
12 goes through an array, compares adjacent elements and
Both do not match, so continue search in right sub- swaps them if they are in wrong order. It is the simples and
list since 12 > 10. most inefficient at the same time.
Consider the array A below to be sorted using bubble sort.
Step 3: Compare 12 with middle element 12
middle = (1+1) div 2 = 1
A[1] = 12 A = 14 33 27 35 10

[0] [1] [2] [3] [4] [5]

12
12

__________________
© 2023/0795 CSC/Notes 38
Pass 1: Insertion Sort
14 33 27 35 10 Insertion sort sorts an array by iterating down the array such
14 33 27 35 10 swap that the part of the array already covered is sorted and the
14 27 33 35 10 current element is inserted into its correct position in the
14 27 33 35 10 swap sorted array by shifting all the elements which are greater
than the current element, to one position ahead.
14 27 33 10 35
Consider the array A below to be sorted using insertion sort.
Pass 2:
14 27 33 10 35 A = 14 33 27 35 10
14 27 33 10 35
14 27 33 10 35 swap Pass 1:
14 27 10 33 35 33
14 27 35 10
Pass 3: 14 33 27 35 10
14 27 10 33 35
14 27 10 33 35 swap Pass 2:
14 10 27 33 35 27
14 33 35 10
Pass 4: 14 33 35 10
14 10 27 33 35 swap 14 27 33 35 10
10 14 27 33 35
Pass 3:
procedure bubblesort(a[],size)≡ 35
for i ← 0 to size-1 do 14 27 33 10
for j ← 0 to size-i-1 do 14 27 33 35 10
if(a[j] > a[j+1])then
temp ← a[j] Pass 4:
a[j] ← a[j+1]
10
a[j+1] ← temp
endif 14 27 33 35
next j 14 27 33 35
next i 14 27 33 35
endprocedure 14 27 33 35
10 14 27 33 35
__________________
© 2023/0795 CSC/Notes 39
Pass 2:
procedure insertsort(a[],size)≡
for i ← 0 to size-1 do 10 33 27 35 14
key ← a[i] 10 33 27 35 14
j ← i 10 33 27 35 14 swap
while(j > 0 and a[j-1] > key)do 10 14 27 35 33
a[j] ← a[j-1]
j ← j - 1
endwhile Pass 3:
a[j] ← key 10 14 27 35 33
next i 10 14 27 35 33
endprocedure 10 14 27 35 33

Pass 4:
Selection Sort
10 14 27 35 33 swap
Selection sort sorts an array by repeatedly selecting the
10 14 27 33 35
smallest remaining element and moving it to the end of a
growing sorted list. The first element in the unsorted part of
the array is compared with all the elements to the right hand procedure selectsort(a[],size)≡
side. If it is not the smallest element, then its position is for i ← 0 to size-1 do
swapped with the smallest element. indexofmin ← i
for j ← i+1 to size-1 do
Consider the array A below to be sorted using selection sort.
if(a[j] > a[indexofmin])then
indexofmin ← j
endif
A = 14 33 27 35 10
next j
if indexofmin ≠ i then
Pass 1: temp ← a[indexofmin]
14 33 27 35 10 a[indexofmin] ← a[i]
a[i] ← temp
14 33 27 35 10
endif
14 33 27 35 10 next i
14 33 27 35 10 Swap endprocedure
10 33 27 35 14

__________________
© 2023/0795 CSC/Notes 40
9.4. Complexity of Algorithms The running time T(n) of this algorithm can be calculated as
follows:
Sometimes, there is more than one algorithm for solving a problem.
We need to know how to compare the performance of different
algorithms in order to choose the best one to solve a particular Number of times
Statement
problem. The efficiency or performance of an algorithm relates to the Executed
resources required by it, such as how quickly it will run, or how much 1 0
computer memory it will use. While comparing or analyzing 2 1
algorithms, we mostly consider the time complexity and space 3 1
complexity. 4 1
5 n + 1
9.4.1. Time Complexity 6 n
Time complexity is a measure of the amount of time 7 n
required to execute an algorithm for solving a problem of a 8 n
particular size. It is expressed as the number of times the
9 0
algorithm’s basic operations are executed on input of size n.
time in seconds is not used because there are too many 10 1
factors that can vary like the speed of the computer, choice 11 0
of a programming language, and the choice of compiler and
execution environment. T(n) = 1+1+1+(n+1)+n+n+n+1
As an illustration, let’s consider a pseudo code algorithm = 4n + 5
that calculates the mean (average) of a set of n numbers.
Time Complexity Functions
1. begin
2. get n Some algorithms perform differently on various inputs of
3. sum← 0 similar size. For example, a search algorithm may perform
4. i← 0 differently when searching for an element in different arrays
5. while i < n do of same size. When comparing algorithms, it is helpful to
6. get num consider the best-case, average-case and worst-case time
7. sum← sum + num efficiencies of the algorithms.
8. i← i + 1
9. endwhile  Best-Case Time Complexity
10. print "mean = ", sum/n The best case time complexity of an algorithm is the
11. end
function defined by the minimum number of operations
performed, taken across all instances of n.

__________________
© 2023/0795 CSC/Notes 41
 Average-Case Time Complexity This simply means that if the input size n doubles, the
The average case time complexity of an algorithm is the algorithm will take four times longer to execute and the
function defined by an average number of operations order of growth is said to be quadratic.
performed, taken across all instances of size n.
Time Complexity Description
 Worst-Case Time Complexity Number of operations is always the
same regardless of the input size.
The worst case time complexity of an algorithm is the
O(1)or The execution time is independent
function defined by the maximum number of operations Constant Time of the size of the input. E.g.
performed, taken across all instances of size n. The worst accessing an array element using
time complexity estimates the time required for the most an index.
time consuming input of each size. Number of operations is always
O(log n) or
proportional to the logarithm of the
Logarithmic Time
input size. E.g. binary search.
Order of Growth
Number of operations is
When analyzing the time complexity of algorithms, we use a proportional to the input size.
notation called Big-O, which gives us an upper limit of the Execution time is increase
O(n) or
execution time; that is, the execution time in the worst case. proportionately as the size of the
Linear Time
In other words, Big-O notation is used to classify algorithms input increases. Any program that
uses a single loop. E.g. linear
by their worst case running time. With such a notation it is
search
easy to compare different algorithms because the notation
Number of operations is
tells clearly how the algorithm scales when the input size proportional to the square of the
increases. This is often called the order of growth. O(n2) or input size. Algorithms with a
Suppose that the execution time for an algorithm of input Quadratic Time nested loop will have a quadratic
size n is given by: time complexity. Many sorting
algorithms are O(n2).
Number of operations is
T(n) = 4n2 + 2n + 2
proportional to the input size raised
to some constant power. An
In the above function, as n grows bigger and bigger, the term O(nk) or
algorithm that contains k nested
Polynomial Time
that will make the most difference is n2. Ignoring constants loops, each with a number of steps
and slower growing terms as they are relatively insignificant proportional to the input size n,
for large inputs, we could say that "T(n) grows at the order will take time proportional to nk.
Number of operations is
of n2" and write:
proportional to some constant k
2
O(kn) or raised to a power equivalent to the
T(n) = O(n ) Exponential Time input size. Exponential time
computations are generally not
practical.

__________________
© 2023/0795 CSC/Notes 42
9.4.2. Complexity of Search and Sorting Algorithms Number of Comparisons (worst case):O(log n)
The basic operation of a searching is comparison. Thus the  Worst case occurs when the target element is not in the
complexity of a search algorithm is calculated in terms of the array.
number of comparisons the algorithm performs in the best,
average and worst cases. Bubble Sort
The basic operations of sorting algorithms are comparisons Number of Comparisons (worst case):
and copy or swap. When the complexity of a sorting
(n-1)+(n-2)+(n-3)+…+3+2+1 = n*(n-1)/2
algorithm is calculated, usually only one of the basic
= (n2 – n)/2
operations is counted.
= O(n2)
Linear Search Number of Swaps (worst case):
Number of Comparisons (Best case): 1 = O(1) (n-1)+(n-2)+(n-3)+…+3+2+1 = n*(n-1)/2
 Best case occurs when the element sought is the first = O(n2)
element in the array. Insertion Sort
Number of Comparisons (worst case):
Number of Comparisons (Average case): n/2 = O(n)
(n-1)+(n-2)+(n-3)+…+3+2+1 = n*(n-1)/2
 Average case occurs when the target element is = O(n2)
somewhere in the middle of the array.
Number of Swaps (worst case):
Number of Comparisons (worst case):(n-1) = O(n) (n-1)+(n-2)+(n-3)+…+3+2+1 = n*(n-1)/2
= O(n2)
 Worst case occurs when the target element is the last
element in the array or does not exist in the array. Selection Sort
Number of Comparisons (worst case):
Binary Search
(n-1)+(n-2)+(n-3)+…+3+2+1 = n*(n-1)/2
Number of Comparisons (Best case): 1 = O(1) = O(n2)
 Best case occurs when the target element is in the middle
of the array.
Number of Swaps (worst case):(n-1) = O(n)
Number of Comparisons (Average case): O(log n)
9.4.3. Limits of Computation
 Technically, some statistical analysis needed here which
is beyond our scope. Computational problems such as searching, sorting, etc. can
be classified into one of two categories: tractable and
intractable.

__________________
© 2023/0795 CSC/Notes 43
Tractable Problems returning to a given city. To calculate all possible routes
 The tractability of a problem refers to how difficult the (and choose the shortest one) requires the calculation of
permutations: the first city is known, then there are n-1
problem is in terms of the amount of time it takes for the
problem to be solved. This is related to the time choices for the second city, n-2 for the third city etc., and
complexity of the problem. this is equal to (n-1)*(n-2)*…*3*2*1 = (n-1)!

 A tractable problem is a problem that is solvable within


Heuristics
a reasonable time frame as the size of the input
increases. That is, there exists an algorithm that can  Heuristics, sometimes called heuristic functions, are
solve the problem in polynomial time or less. used to provide "good enough" solutions to very
complex problems where finding a perfect solution
 Problems with O(1), O(log n), O(n), O(n log n), would take too much time. When we use heuristics, we
and O(nk) complexities are tractable. trade accuracy, correctness, and exactness for speedy
processing.
Intractable Problems
 To tackle an in intractable problem, heuristic methods
 An intractable problem is a problem for which there are applied. Heuristics are approaches that are "best fit",
exist no efficient algorithm to solve it. Theoretically they that is, they return solutions that are not entirely
are solvable but are classified as "insoluble" due to accurate, optimal or complete, but are fit for purpose and
limits of computation – due to the speed of today’s achievable in a reasonable time frame.
technology, it may take millions of years to solve.
 For the travelling salesman problem, a heuristic method
Problems that grow exponentially or worse are said to be
follows the principle of each time selecting the nearest
intractable.
unvisited city (instead of checking the routes via all the
 Most intractable problems have an algorithm that remaining cities). In this way, the algorithm finds a route
provides a solution and that algorithm is a brute-force in a feasible number of steps, but the solution is not
search. This algorithm does not provide an efficient necessarily the shortest path.
solution and is therefore, not feasible for computation
with anything more than the smallest input. Non-Computable Problems
 Problems with exponential time complexity (O(2 )) or n
 Not every problem can be solved algorithmically, for
factorial time complexity (O(n!)) complexity are example, the Halting problem.
intractable.  The Halting problem: it is impossible to write an
algorithm to determine if another algorithm will finish
 For example: the travelling salesman problem is a well-
with a given input.
studied intractable problem: it has an order of growth of
 The Halting problem demonstrates that there are some
O(n!). The problem requires the calculation of the
problems which cannot be solved by a computer.
shortest route to visit a list of cities starting from and

__________________
© 2023/0795 CSC/Notes 44
9.5. Programming Concepts However, programs written for one type of computer are tied
to that particular computer and cannot be executed on
Computers can do such a wide variety of things because they can be
another type of computer, making them machine dependent.
programmed. This means that computers are not designed to do just
one job, but to do any job that their programs tell them to do. A This is because each brand of CPU has its own machine
program is a set of instructions that a computer follows to perform a language instruction set. Machine language is the first
generation of computer languages (1GL).
task. Microsoft Word is a word processing program that allows you to
create, edit, and print documents with your computer. Adobe
Photoshop is an image editing program that allows you to work with Advantages Disadvantages
graphic images, such as photos taken with your digital camera.  Machine language x Machine language is
Computer programming is the act of writing computer programs. A programs run very fast machine dependent or
person with the training and skills necessary to write computer not portable
programs is called a programmer. Programmers write computer  Machine language does
x Writing programs in
programs by translating algorithms into a language that a computer can not require a translator
machine language is
understand. A programming language is a formal language that is used tedious and error prone
for writing computer programs. There exist more than 2500
programming languages in the world. Some examples of the most
widely used programming languages are FORTRAN, COBOL, Basic, Assembly Language
C, SQL, C++, Perl, Java, Python, Ruby, PHP, JavaScript, Pascal, Assembly language is a low-level language that uses
Logo and Prolog. abbreviations or mnemonics to represent the instructions that
Programming languages can be grouped into low-level languages and the computer will execute. Like with machine language, each
high-level languages. brand of CPU has its own assembly language. As such,
assembly language is tied to specific computer hardware and
programs written for one type of computer cannot execute on
9.5.1. Low-Level Languages
another type of computer. Assembly language cannot be
A low level language is a computer language that reflects the executed by the CPU directly. A special program called
processor architecture or that is closer to the CPU instruction assembler is used to translate assembly language programs
set. Low-level languages are machine dependent. They to a machine language. Each assembly language instruction
consist of machine language and assembly language. translates to one and only one machine code instruction. This
means that there is a one-to-one mapping between assembly
Machine Language language instructions and machine language instructions.
Machine language is a low-level language that uses binary Assembly language is the second generation of computer
codes (or 0’s and 1’s) to represent the instructions that the language (2GL).
computer will execute. Since machine language is made of
0’s and 1’s, programs written in machine language do not
need to be translated for the computer to understand.

__________________
© 2023/0795 CSC/Notes 45
Advantages Disadvantages which they will run. A language translator is a computer
program that translates program instructions from one
 Assembly language x Assembly language is
computer language to another, without loss of original
programs run very fast machine dependent (not
portable) meaning. There are three types of language translators:
assembler, compiler and interpreter.
 They allow close
control of the CPU. x Writing programs in
assembly language is (a) Compiler
time consuming and A compiler is a program that translates an entire
error prone
program written in high-level language into an object
x Programmer needs to program in machine language. The original version of
know a lot of detail the program in high-level language is called source
about how the CPU code/program and the generated machine language
works. program is called object code. This process is called
compilation. Examples of compiled languages are
Ada, C, Pascal, Java and Python.
9.5.2. High-Level Languages
High-level language is a computer language that uses
English-like words to represent the instructions that the Advantages Disadvantages
computer will execute. In other words, it is a computer  It is fast since it x Object code is not
language that is closer to human language, making high- translates the entire produced if there are
level languages more user-friendly than low-level languages. program before syntax errors
In practice, every computer language above assembly execution
language is a high-level language. Programs written in high- x If an error is
level language are translated to machine language by a  The object code corrected, the whole
produced can be used program needs to be
compiler or an interpreter. Each high-level language
whenever required recompiled
instruction or statement translates to many machine language without need for
instructions (one-to-many mapping). High-level language is recompilation x It is a larger program
the third generation of computer languages (3GL). Examples than other translators,
of high-level languages are Ada, BASIC, C, FORTRAN, so occupies much
Java, Pascal and Python. space in memory

Language Translators (b) Interpreter


A computer cannot execute a program written in any An interpreter is a program that translates and then
language other than its machine language. Programs written executes instructions from a high-level program line
in assembly language or high-level language must be by line. An interpreter translates an instruction and
translated to the machine language of the computers on allows it to be executed before translating the next
__________________
© 2023/0795 CSC/Notes 46
instruction. This means that if a program performs a Advantages Disadvantages
section code 1000 times, then the section is translated
 Assembly x Assembly language is
into machine code 1000 times since each line is
language machine dependent or
interpreted and then executed. programs run not portable
Examples of interpreted languages are JavaScript, very fast
LISP, Perl, PHP and HTML. Some languages like x Writing programs in
BASIC are generally interpreted but can also be  They allow close assembly language is
compiled. control of the time consuming and
CPU error prone

Advantages Disadvantages  It occupies little x Programmer needs to


memory space so know a lot of detail
 It is good at locating x It is slow as can be used in about how the CPU
errors as translation interpretation and small systems works.
is done line by line execution are done with limited
line by line memory space
 If an error is
corrected, there is no x Translation is done
need to retranslate every time the Program Errors
the whole program program executes Each high-level language has its own set of words and rules
since no object code is that the programmer must use to write a program. These
 It occupies little produced
words are known as keywords or reserved words while the
memory space so can
be used in small x The program cannot rules to be used are called syntax. Each keyword has a
systems with limited run without an specific meaning and cannot be used for any other purpose.
memory space interpreter
(a) Syntax Errors
(c) Assembler Syntax refers to the set of rules that define the
An assembler is a program that translates an assembly structure of legal statements in a language. It is the
language program into machine language. The process grammar of a language. Syntax rules specify how the
is called assembling. An assembler that runs on a keywords and symbols of a programming language
computer and produces the machine codes for the can be put together to form meaningful statements.
same computer is called self-assembler or resident When writing programs, non-respect of the syntax
assembler while an assembler that runs on a computer rules of the language used results in syntax errors. A
and produces machine codes for another computer is syntax error will stop the compiler or interpreter to
called cross assembler. stop trying to generate the machine code and will not
create an executable. However, a compiler will usually
not stop at the first error it encounters but will
__________________
© 2023/0795 CSC/Notes 47
continue checking the syntax of a program until the (c) Runtime Errors
last line. A runtime error occurs during program execution. For
Examples of syntax errors are: a misspelled keyword, example, a run-time error may occur if division by 0 is
a missing punctuation mark and the incorrect use of an attempted or if invalid inputs are entered by the user.
operator. A runtime error may cause the program to stop
execution, or it may be handled by an error-trapping
(b) Semantic Errors routine. Runtime errors are commonly referred to as
Semantics refers to the meaning of a well-formed bugs, and are often found during the debugging
statement. Semantic rules specify the relationship process, before software is released. When runtime
between the words and symbols of a language and errors are found after a program has been distributed to
their intended meaning. Ultimately, without semantics the public, developers often release patches, or small
a programming language is just a collection of updates, designed to fix the errors.
meaningless phrases. A statement can be syntactically
9.5.3. Programming Paradigms
correct but semantically incorrect. That is, a statement
can be written in an acceptable form and still conveys High-level languages can be grouped into different
the wrong meaning. Compilation and interpretation do paradigms. The word paradigm comes from the Greek word
not detect semantic errors; they are detected from "paradigma" which means model or pattern. A programming
wrong results. Semantic errors are also called logic paradigm can therefore be defined as a model for a class of
errors. programming languages that share common characteristics.
Syntax errors are easy to find and correct because the In simpler terms, a programming paradigm is a style or way
compiler or interpreter finds them for you. On the of programming. Each paradigm describes the approach a
other hand, a semantic error is often very difficult to language in that paradigm uses to solve a problem. The most
find. If you write a statement that is syntactically common programming paradigms are imperative,
correct, the computer will understand and execute it. procedural, declarative and object-oriented paradigms.
However, if you accidentally told it to do something
that you did not really intend, you would have made a Imperative Paradigm
logical or semantic error. For example, if a This is a programming paradigm in which a program is
programmer accidentally multiplies two variables expressed as a sequence commands that change the state of
when they meant to divide them, the program will give the program. The state of a program is given by the contents
an incorrect result, but no error message. Syntax errors of variables that make up the program. Variables in such
are errors of grammar whereas, logic or semantic languages point to memory locations which are modified as
errors are errors of meaning. the program executes, thereby, changing the state of the
program. Another characteristic of this paradigm is that a
program describes how to solve a particular class of
problems by describing in details the steps that are necessary
__________________
© 2023/0795 CSC/Notes 48
to find a solution. Examples of imperative languages are itself a function that calls other functions as its
Ada, C, COBOL, FORTRAN, and Pascal. arguments. Examples of functional languages are
Features of imperative languages are: variable declaration, Haskell, LISP, ML and Scheme.
assignment, control structures (sequence, selection and Lambda calculus forms the basis of almost all
iteration), recursion and side effects. functional programming languages. Lambda calculus
is the use of lambda expressions to define functions. A
Procedural Paradigm lambda expression is a formula that defines a function.
This is a subtype of imperative paradigm based upon the For example: .
concept of subprogram calls. A subprogram is a named Examples
sequence of statements for performing a specific task, which  A function that returns the sum of two integers
can be used whenever that task is needed. Subprograms are add :: (int,int) int
called by other names including procedures, functions, and
add x y = x + y
subroutines. Today, all imperative languages are procedural
making the term imperative programming synonymous to
procedural programming.  A function that returns the length of a list (array)
length :: [a] → int
Declarative Paradigm length[] = 0
This is a programming paradigm in which a program length[_:xs] = 1 + length xs
expresses the logic of a computation without describing its
control flow. The logic of a program describes what to do to (b) Logic Paradigm
solve a problem while the control flow describes how to In this paradigm, a program is a collection of facts and
solve the problem. Programming in a declarative language,
rules involving relational expressions. A program
the programmer concentrates more on what is to be done to written in a logic programming language is a set of
solve the problem while the how part is left in the hands of
sentences in logical form, expressing facts and rules
the language compiler or interpreter. Examples of declarative
about some problem domain. It is based on formal
languages are Haskell, LISP, Scheme, and Prolog.
logic defined by Greek mathematicians and later
Some important features of declarative languages are developed into first-order predicate calculus. An
recursion and backtracking. example of a logic programming language is
The declarative paradigm includes a number of well-known PROLOG (PROgramming LOGic) that was developed
paradigms like functional paradigm and logic paradigm. for artificial intelligence.

(a) Functional Paradigm


In this paradigm, a program treats computation as the
evaluation of mathematical functions; a program is
__________________
© 2023/0795 CSC/Notes 49
Object Oriented Paradigm (c) Abstraction
This is a programming paradigm in which a program is a Abstraction is the process of representing important
collection of objects which interact with each other by details and hiding away the unnecessary details.
sending messages. An object here is an entity containing Through abstraction unnecessary details are removed
both data and operations that manipulate the data. The data so that one can focus on only the relevant parts of a
or attributes of the object represent the state of the object and problem in order to solve it. Abstraction tries to
the operations or methods represent the behavior of the minimize details so that the programmer can focus on
object. For example, a Person object can have the attributes a few concepts at a time. For example, functions use
name, gender, DOB, height, and the methods walk, stop, sit, the concept of abstraction.
run, and jump. Some important features of OOP are class, The following are the advantages of abstraction.
object, abstraction, encapsulation, inheritance and o The programmer does not have to write the low-
polymorphism. Examples of object-oriented languages are level code.
C++, Objective C, Java, Python, Visual Basic and Smalltalk. o The programmer does not have to specify all the
register/binary-level steps or care about the
(a) Class hardware or instruction set details.
A class is a set of objects that share the same
o Code duplication is avoided and thus programmers
properties and behavior. A class describes an object or
do not have to repeat fairly common tasks every
a real-life concept. Classes act as templates for
time a similar operation is to be performed.
creating objects, providing initial values for instance
variables (properties) and the bodies for methods o It allows internal implementation details to be
(behavior). All objects generated from the same class changed without affecting the users of the
share the same behavior but have different properties. abstraction.

(b) Object (d) Encapsulation


An object is an instance of a class. An object consists Encapsulation is the process of wrapping up the
of a collection of attributes, representing the state of properties and behavior of an object into a single unit
the object, and a collection of methods, representing called Class. Encapsulation makes the important
the behavior that the object is capable of performing. concept of data hiding possible. It ensures that data
Attributes are sometimes referred to as the fields of an belonging to an object is not accessed directly; it is
object. The methods are routines that are capable of only accessed through the object’s methods, which act
accessing and manipulating the values of the attributes as an "interface" to the object. This is done by making
of the object. Objects interact with each other by properties and methods “private.”
sending messages. When a message is sent to an
object, the corresponding method of the object is (e) Inheritance
executed. Inheritance is the process of forming a new class from
an existing one. The class form which the new class is
__________________
© 2023/0795 CSC/Notes 50
derived is often called the base class, parent class or
Base class
superclass while the derived class is often referred to
as the child class or subclass. The subclass usually
contains all the attributes and methods of the Derived class 1
superclass plus some of its own. For example, the class
Student inheriting from the class Person will have all Derived class 2
the attributes and methods of Person plus the
following:
Inheritance is usually represented using an inheritance
(f) Polymorphism
diagram. For example, if the classes Student and
Polymorphism is the use of different methods, each
Teacher are derived from the superclass Person, this is
with the same name, which are associated with
represented as:
different object types. In other words, it is the ability
for different objects to respond to the same message in
Person
different, class-specific ways. Polymorphic methods
are used which have one name but different
Student Teacher implementations for different classes.
There are a variety of forms that polymorphism can
take:
There are two types of Inheritance: multiple
inheritance and multilevel inheritance. Overloading of Functions
 Multiple inheritance is when a derived class Functions with different parameter lists may have the
inherits features from more than one superclass. It same name. The compiler determines which function
is illustrated as follows: to use by the type of the arguments in the function call.
A function in a superclass may be overridden in a
Base class 1 Base class 2 derived class. Assume you have a “shape” superclass.
This class has a method called “area” which returns
Derived class the area of the shape. Polymorphism allows you to
make subclasses like “circle,” “square,” and “triangle”
which inherit the “area” method, but each subclass
 Multi-level inheritance is when a class inherits would return the correct value even though they have
from a class which is itself inherited from another different formulas to calculate their areas. This is
class. It is illustrated as follows: possible by overriding the area method in all the
subclasses.

__________________
© 2023/0795 CSC/Notes 51
Overloading of Operators Data coupling
An operator can be used in different ways or contexts. Data coupling is when two modules interact with each
The operator + can be used to add pairs of any of the other by means of passing data (as parameter). Two
primitive types and to concatenate strings. When used, components are data coupled if they communicate
the compiler determines the type of its operands. If through parameters. It is the most common form of
they are numeric, they are added but if they are strings, coupling.
they are concatenated.
Control coupling
(g) Cohesion Control coupling is when one module decides the
Cohesion is the degree to which all elements of a class, function of another module or changes its flow of
module or component work together as a functional execution. Two components are control coupled if one
unit. In other words, it is a measure of how well a passes to the other a piece of information intended to
class, module or component fits together. A highly control the internal logic of another.
cohesive component should implement a single logical
function or should implement a single logical entity. Cohesion and coupling deal with quality of an OO
High cohesion is good, and low cohesion is bad. design. Whereas coupling describes the relationships
Benefits of high cohesion are: between modules, cohesion describes the relationships
 It increases module reusability within modules. Generally, a good OO design should
 It increases module maintainability be loosely coupled and highly cohesive.
 It reduces module complexity

(h) Coupling
Coupling is the measure of the strength of association
established by a connection of one module to another.
In other words, it is the degree of interdependence
between two or more classes, modules or components.
High (tight) coupling is bad and low (loose) coupling
is good. High coupling complicates a system, since a
module is harder to understand, change, or correct if it
is highly interrelated by other modules. Low coupling
allows components to be used independently from
other components.
Two types of coupling are data coupling and control
coupling:

__________________
© 2023/0795 CSC/Notes 52

You might also like