AL CSC Notes - Part 3 (2023)
AL CSC Notes - Part 3 (2023)
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 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];
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:
__________________
© 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:
__________________
© 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.
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:
__________________
© 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
__________________
© 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.
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.
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
__________________
© 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
__________________
© 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
__________________
© 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.
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.
__________________
© 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.
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
__________________
© 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)!
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.
__________________
© 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
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)!
__________________
© 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
__________________
© 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