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

Introduction to problem solving

Problem-solving is a skill and process that involves defining a problem, analyzing it, establishing goals, generating possible solutions, analyzing those solutions, and implementing the chosen solution. Algorithms and data structures play a crucial role in problem-solving, particularly in computer science, where they help efficiently organize and process data. Various types of data structures, such as linear and non-linear, are used to optimize algorithm efficiency and simplify complex problems.

Uploaded by

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

Introduction to problem solving

Problem-solving is a skill and process that involves defining a problem, analyzing it, establishing goals, generating possible solutions, analyzing those solutions, and implementing the chosen solution. Algorithms and data structures play a crucial role in problem-solving, particularly in computer science, where they help efficiently organize and process data. Various types of data structures, such as linear and non-linear, are used to optimize algorithm efficiency and simplify complex problems.

Uploaded by

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

WHAT IS PROBLEM-SOLVING?

Problem-solving is a tool, a skill, and a process. As a tool is helps you solve a problem or achieve a goal. As a
skill you can use it repeatedly throughout your life. And, as a process it involves a number of steps.
It is not unusual for problems to arise when you are working towards a goal and encounter obstacles along the
way. Students usually have many and varied goals, both related to school and to other areas of their lives, and it
is likely that you will encounter barriers to your success at times. As these barriers are encountered, problem-
solving strategies can be utilized to help you overcome the obstacle and achieve your goal. With each use of
problem-solving strategies, these skills become more refined and integrated so that eventually their use becomes
second nature.
THE PROBLEM-SOLVING PROCESS
Step 1 - Problem Definition
Before you are ready to take any steps to solve the problem, you first have to be sure that you are clear about
what the problem really is. It can be easy to get distracted by solving a different problem than what is actually
causing distress if it is easier than dealing with the real problem. This step involves thinking about the following
questions:

1. How is the current situation different from what I actually want it to be?
2. What do I actually want, or how do I actually want things to be?
3. What is preventing me from achieving my goals, or from things being the way I want them to be?

It can be very helpful to write down the answers to these questions so that you are forced to clarify that the
problem you are defining is the actual one you want to solve. Just thinking about things in your head can cause
confusion and end up distracting you from the actual problem at hand.
If you are dealing with more than one problem at a time, it may be helpful to prioritize them. That way you can
focus on each one individually, and give them all the attention they require.
Step 2 – Problem Analysis
Once you have defined the problem, you need to think about it from different perspectives to insure that you
understand all the dimensions of the problem.
The following questions can be useful to help you analyze the problem.

1. How is this problem affecting me?


2. How is this problem affecting other people?
3. Who else is experiencing this problem?
4. How do other people deal with this problem?

After you have completed this step, check to make sure that your definition of the problem still fits. It is not
unusual at this point to find that the problem you really want to solve is different than the one you initially
identified.
STEP 3 – ESTABLISH YOUR GOALS
Once you have looked at the problem from different perspectives, you can decide what you want to achieve and
establish your goals. You need to answer the very specific question – “What is my immediate goal?”
Examples:

 Improve my time management skills


 Complete assignments on time
 Improve my grades

1
STEP 4 – GENERATE POSSIBLE SOLUTIONS
During this stage the goal is to generate as many possible solutions as you can. Do not worry about whether or
not they are realistic, practical, or effective. Frequently a solution you might eliminate initially, with work can
be developed into a very effective solution.
It can be very helpful to ask yourself what you have done in the past when faced with similar problems, and
how other people you know have dealt with similar situations. In addition, you can also approach friends,
family, a counselor, teachers, books, or the internet, etc. to obtain ideas for solutions. Be sure to write down all
the possibilities you generate so that you can approach this task systematically.
STEP 5 – ANALYZE THE SOLUTION
During this stage, you will examine each alternative and write down both the advantages and disadvantages to
each. Some considerations to keep in mind include:

 Is it relevant to my situation?
 Is it realistic?
 Is it manageable?
 What are the consequences – both good and bad?
 What is the likelihood that it is going to help me reach my goal?

STEP 6 - IMPLEMENTATION
The last step is to implement the solution you have chosen. This step involves identification of all the steps
necessary to implement it, and also on-going monitoring of the effectiveness of the solution to make sure that it
actually solved the problem. During this stage of the process, ask yourself the following questions:

1. How effective is the solution?


2. Did it achieve what I wanted?
3. What consequences (good and bad) did it have in my situation?

If the solution was successful in helping you solve your problem, then you can feel satisfied with your efforts
and what you learned. If you feel dissatisfied in some way, you can either modify the solution to work better, or
you can scrap it and turn to other alternative solutions, or begin the process again.
Remember that problem-solving is a cycle – it involves searching for a solution to a problem that will lead to
various possible solutions which then need to be evaluated. If the problem is solved, then you have found an
effective solution. If the problem has not been solved, then you start the process again.
INTRODUCTION TO DATA STRUCTURE AND ALGORITHM
Computer science is a field of study that deals with solving a variety of problems by using computers. The
problem to be solved could be as simple as performing the addition of two numbers, or as complex as designing
a robot capable of making decisions in a real-time environment. To solve a given problem by using computer,
you need to design an algorithm for it. The nature of an algorithm often depends closely on the nature of the
data on which the algorithm works. Therefore, the study of algorithms also involves the study of the data
structures that algorithms work on.
ROLE OF ALGORITHM AND DATA STRUCTURE IN PROBLEM SOLVING
Problem solving is an essential part of every scientific discipline. In today’s world, computers are widely used
to solve problems pertaining to various domains, such as banking, commerce, medicine, manufacturing, and
transport.
To solve a given problem by using a computer, you need to write a program for it. A program consists of two
components, algorithm and data structure.

2
Many different algorithms can be used to solve the same problem. Similarly, various types of data structures
can be used to represent a problem in a computer.
To solve the problem in an efficient manner, you need to select a combination of algorithms and data structures
that provide maximum efficiency.
ROLE OF ALGORITHM
The word algorithm is derived from the name of the Persian mathematician Al Khwarizmi.
Algorithms can be defined as a step-by-step procedure for solving a problem. It helps the user arrive at the
correct result in a finite number of steps. Consider the following step-by-step procedure to display the first 10
natural numbers:-
1. Set the value of counter to 1
2. Display counter
3. Increment counter by 1
4. If counter <=10, go to step 2
The preceding step-by-step procedure is an algorithm because it produces the correct result in a finite number of
steps.
AN ALGORITHM HAS FIVE IMPORTANT PROPERTIES: -
 Finiteness: An algorithm terminates after a finite number of steps.
 Definiteness: Each step in an algorithm is unambiguous. This means that the action specified by the
step cannot be interpreted in multiple ways and can be performed without any confusion.
 Input: An algorithm accepts zero or more inputs.
 Output: An algorithm produces at least one output.
 Effectiveness: An algorithm consists of basic instructions that are realizable. This means that the
instructions can be performed by using the given inputs in a finite amount of time.
A problem can be solved by using a computer only if an algorithm can be written for it. In addition, the use of
algorithm provides many other benefits:-
 While writing an algorithm, you identify the step-by-step procedure, the major decision points, and the
variables necessary to solve the problem. This helps you in the development of the corresponding
program.
 Identification of the procedure and the decision points reduces the problem into a series of smaller
problems of more manageable size. Therefore, problems that would be difficult or impossible to solve as
a whole can be approached as a series of small solvable sub problems.
 With the use of an algorithm, decision making becomes a more rational process. This is because
algorithms comprise of sub tasks, where each sub task is atomic in nature and is supported by facts.
 With the use of an algorithm, the same specified steps are used for performing the tasks. This makes the
process more consistent and reliable.
ROLE OF DATA STRUCTURE
Multiple algorithms can be designed to solve a particular problem. However, the algorithm may differ in how
efficiently they can solve the problem. In such a situation, an algorithm that provides the maximum efficiency
should be used for solving the problem. Efficiency here means that the algorithm should work in minimal time
and use minimal memory.
One of the basic techniques for improving the efficiency of algorithms is to structure the data that they operate
on in such a way that the resulting operations can be efficiently performed.

3
The way in which the various data elements are organized in memory with respect to each other is called a data
structure. Data can be organized in many different ways; therefore, you can create as many data structures as
you want. However, there are some standard data structures that have proved useful over the years. These
include arrays, linked lists, stacks, queues, trees and graphs.
All these data structures are designed to hold a collection of data items. However, the differences lies in the
way the data items are arranged with respect to each other and the operations that they allow. Because of the
different ways in which the data items are arranged with respect to each other, some data structures prove to be
more efficient that others to solve a given problem.
Suppose you have to write an algorithm that enables printer to service the requests of multiple users on a first-
come-first-served (FCFS) basis. In this case, using a data structure that stores and retrieves the requests in the
order of their arrival would be much more efficient than a data structure that stores and retrieves the requests in
a random order.
In addition to improving the efficiency of an algorithm, the use of appropriate data structures also allows you to
overcome some other programming challenges, such as:-
 Simplifying complex problems
 Creating standard, reusable code components
 Creating programs that are easy to understand and maintain
A data structure is a storage that is used to store and organize data. It is a way of arranging data on a
computer so that it can be accessed and updated efficiently.

A data structure is not only used for organizing the data. It is also used for processing, retrieving, and
storing data. There are different basic and advanced types of data structures that are used in almost every
program or software system that has been developed. So, we must have good knowledge about data
structures.
Data Structures are the programmatic way of storing data so that data can be used efficiently. Almost
every enterprise application uses various types of data structures in one or the other way.
Data structures are an integral part of computers used for the arrangement of data in memory. They are
essential and responsible for organizing, processing, accessing, and storing data efficiently. But this is not
all. Various types of data structures have their own characteristics, features, applications, advantages, and
disadvantages.
Example:
Consider an example where you have to find the maximum value in a set of 50 numbers, In this scenario, you
can either use 50 variables or a data structure, such as an array of size 50, to store the numbers. When 50
different variables are used to store the numbers, the algorithm to determine the maximum value among the
numbers can be written as:
1. Accept 50 numbers and store them in num1, num2, num3, .. num50
2. Set max = num1
3. If num2 > max then: max = num2
4. If num3 > max then: max = num3
:
5. If num50 > max then max = num50
6. Display max

On the other hand, when an array of size 50 is used, the algorithm can be written as:-
4
1. Set max = num [0]
2. Repeat step3 varying i from 1 to 49
3. If num[i] > max then: max = num[i]
4. Display max
From the preceding two algorithms, it can be seen that the algorithm using an array manipulates memory much
more efficiently than the algorithm using 50 variables. Also, the algorithm using an array involves few steps
and is therefore, easier to understand and implement as compared to the algorithm that uses 50 variables.
Data structures also enable the creation of reusable code components. Suppose you have created a class to
implement a data structure that stores and retrieves requests in the order of their arrival. Once the class is
created, the same class can be used in several different applications that need to service the requests of multiple
users on a FCFS basis.
This means that a data structure once implemented can be used as a standard component to provide a standard
solution to a specific set of problems. The use of standard components helps simplify the maintenance process.
This is because the standard components are time tested and therefore, do not need much maintenance.
Classification of Data Structure
Data structure has many different uses in our daily life. There are many different data structures that are used
to solve different mathematical and logical problems. By using data structure, one can organize and process a
very large amount of data in a relatively short period. Let’s look at different data structures that are used in
different situations.

Classification of Data Structure

 Linear data structure: Data structure in which data elements are arranged sequentially or
linearly, where each element is attached to its previous and next adjacent elements, is called a
linear data structure.
Examples of linear data structures are array, stack, queue, linked list, etc.
 Static data structure: Static data structure has a fixed memory size. It is easier to
access the elements in a static data structure.
An example of this data structure is an array.
 Dynamic data structure: In the dynamic data structure, the size is not fixed. It can be
randomly updated during the runtime which may be considered efficient concerning the
memory (space) complexity of the code.
Examples of this data structure are queue, stack, etc.
 Non-linear data structure: Data structures where data elements are not placed sequentially or
linearly are called non-linear data structures. In a non-linear data structure, we can’t traverse all
the elements in a single run only.
Examples of non-linear data structures are trees and graphs.

5
Note: Arrays and linked lists are basic data structures that are used to implement other data structures such as
stacks, queues, trees and graphs.
An array is always a static data structure, and a linked list is always a dynamic data structure. However, the
other data structures can be static or dynamic depending on whether they are implemented using an array or a
linked list.
DESIGNING ALGORITHM AND MEASURING THEIR EFFICIENCY
Designing an algorithm for a given problem is a difficult intellectual exercise. This is because there is no
systematic method for designing an algorithm. Moreover, there may exist more than one algorithm to solve a
problem, writing an effective algorithm for a new problem or writing a better algorithm for an already existing
one is an art as well as science because it requires both creativity and insight.
TECHNIQUE FOR DESIGNING ALGORITHM
Although there is no systematic method for designing an algorithm, there are some well-known techniques that
have proved to be quite useful in designing algorithms. Two commonly used techniques for designing
algorithms are:-

 DIVIDE AND CONQUER APPROACH

The divide and conquer approach is an algorithm design technique that involves breaking down the problem
recursively into sub problems until the sub problems become so small that they can directly be solved. The
solutions to the sub problems are then combined to give a solution to the original problem.
Divide and conquer is a powerful approach for solving conceptually difficult problems. It simply requires you
to find a way of:-

1. Breaking the problem into sub problems


2. Solving the trivial cases.
3. Combining the solutions of the sub problems to solve the original problem.

Divide and conquer often provides a natural way to design efficient algorithms.

Consider an example where you have to find the minimum value in a list of numbers. The lists are as shown in
the figure:-

To find the minimum value, you can divide the list into two halves, as shown in the following figure: -

Again, divide each of the two lists into two halves as shown in the following figure: -

Now, there are only two elements in each list. At this stage, compare the two elements in each lists to find the
minimum of the two. The minimum values from each of the four lists is shown in the following figures.

6
Again, compare the first two minimum values to determine their minimum. Also compare the last two minimum
values to determine their minimum. The two minimum values thus obtained are shown in the following figure:
-

Again, compare the two final minimum values to obtain the overall minimum value, which is 1 in the preceding
example.

 GREEDY APPROACH

The greedy approach is an algorithm design technique that selects the best possible option at any given time.
Algorithms based on the greedy approach are used for solving optimization problems, where you need to
maximize profits or minimize costs under a given set of conditions. Some examples of optimization problems
are: -

 Finding the shortest distance from an originating city to a set of destination cities, given the distances
between the pairs of cities.
 Finding the minimum number of currency notes required for an amount, where an arbitrary number of
notes for each denomination are available.
 Selecting items with maximum value from a given set of items, where the total weight of the selected
items cannot exceed a given value.

Consider an example, where you have to fill a bag of capacity 10kg by selecting items, (from a set of items)
whose weights and values are given in the following table.

Item Weight (in kg) Value (in$/kg) Total Value (in $)


A 2 200 400
B 3 150 450
C 4 200 800
D 1 50 50
E 5 100 500

Weights and Values of Items

A greedy algorithm acts greedy, and therefore selects the item with the maximum total value at each stage.
Therefore, first of all, item C with total value of $800 and weight 4 kg will be selected. Next, item E with total
value $500 and weight 5 kg will be selected. The next item with the highest value is item B with a total value of
$450 and weight 3 kg. However, if this item is selected, the total weight of the selected items will be 12 kg (4 +
5 + 3), which is more than the capacity of the bag.

Therefore, we discard item B and search for the item with the next highest value. The item with the next higher
value is item A having a total value of $400 and a total weight of 2 kg. However, the item also cannot be
selected because if it is selected, the total weight of the selected items will be 11 kg (4 + 5 + 2). Now, there is
only one item left, that is, item D with a total value of $50 and a weight of 1 kg. This item can be selected as it
makes the total weight equal to 10 kg.
7
The selected items and their total weights are listed in the following table.
Item Weight (in kg) Total value (in $)
C 4 800
E 5 500
D 1 50
Total 10 1350
Items selected using Greedy Approach

For most problems, greedy algorithms usually fail to find the globally optimal solution. This is because they
usually don’t operate exhaustively on all data. They can make commitments to certain choices too early, which
prevent them from finding the best overall solution later.

This can be seen from the preceding example, where the use of a greedy algorithm selects item with a total
value of $1350 only. However, if the items were selected in the sequence depicted by the following table, the
total value would have been much greater, with the weight being 10 kg only.
Item Weight (in kg ) Total value (in $)
C 4 800
B 3 450
A 2 400
D 1 50
Total 10 1700
Optimal selection of Items

In the preceding example you can observe that the greedy approach commits to item E very early. This prevents
it from determining the best overall solution later. Nevertheless, greedy approach is useful because its quick and
easy to implement. Moreover, it often gives good approximation to the optimal value.
DESIGNING ALGORITHM USING RECURSION
Recursion refers to the technique of defining a process in terms of itself. It is used to solve complex
programming problems that are repetitive in nature.

The basic idea behind recursion is to break a problem into smaller versions of itself, and then build up a solution
for the entire problem. This may sound similar to the divide and conquer technique. However, recursions not
similar to the divide and conquer technique.
Divide and conquer is a theoretical concept that may be implemented in a computer program with the help of
recursion.
Recursion is implemented in a program by using a recursive procedure or function. A recursive procedure is a
function which invokes itself.
Consider a function f(n), which is the sum of the first n natural numbers. This function can be defined in several
different ways.
In mathematics, the function will be defined as: f(n) = 1 + 2 + 3 + …. + n
However, the same function can be defined in a recursive manner as: f(n) = f(n – 1) + n
Where n >1; and f(1) = 1
In this case, the recursive definition of the function f(n) calls the same function, but with its arguments reduced
by one. The recursion will end n = 1, in which case f(1) = 1 has been defined.

8
To understand this concept, consider a factorial function. A factorial function is defined as:-
n! = 1 x 2 x 3 x 4 x .. x n
This same factorial function can be redefined as:-
n! = (n – 1)! x n
Where n > 1; and 0! = 1
This definition of n! is recursive because it refers to itself when it uses (n – 1)!.
The value of n! is explicitly given where n = 0; and the value of n! for arbitrary n is defined in terms of the
smaller value of n, which is closer to the base value 0.
If you have to calculate 3! By using recursion. you first define 3! in terms of 2!:-
3! = (3 x 2!)
Now, you will define 2! in terms of 1!: 3! = (3 x (2 x 1!))
Now, 1! will be defined in terms of 0!: 3! = (3 x (2 x (1 x 0!)))
As, 0! is defined as 1, the expression becomes: 3! = (3 x (2 x (1 x 1)))
3! = (3 x (2 x 1))
3! = (3 x 2)
3! = 6
This recursive algorithm for determining the factorial of a number n can be written as:-

ALGORITHM: FACTORIAL(N)
1. If n = 0, then: //Terminating condition
a. Return (1)
2. Return (n x Factorial (n – 1))
Please note that every recursive algorithm should have a terminating condition. Otherwise, the algorithm will
keep on calling itself infinitely.
The main advantage of recursion is that it is useful in writing clear, short, and simple programs. One of the most
common and interesting problems that can be solved using recursion is the Tower of Hanoi problem.
TOWER OF HANOI PROBLEM
Tower of Hanoi is a classical problem, which consists of n different sized disks and three pins over which these
disks can be mounted. All the disks are placed on the first pin with the largest disk at the bottom and the
remaining disks in decreasing order of their size as shown in the following figure:-

The objective of the game is to move all disks from the first pin to the third pin in the least number of moves by
using the second pin as an intermediary.
To play this game, you need to follow rules: -
 Only one disk can be moved at a time
 A larger disk cannot be placed over a smaller one

9
Let n be the number of the discs. If n = 3, it will require seven moves to transfer all discs from pin one to pin
three, as shown in the table below.
Steps Moves
1 move top disc from pin 1 to pin 3
2 move top disc from pin 1 to pin 2
3 move top disc from pin 3 to pin 2
4 move top disc from pin 1 to pin 3
5 move top disc from pin 2 to pin 1
6 move top disc from pin 2 to pin 3
7 move top disc from pin 1 to pin 3
When n = 2, we should move the top disc from pin 1 to pin 2, move the top disc from pin 1 to pin 3, and then
move the top disc from pin 2 to pin 3.
The solution for n = 1 will be to move the disc from pin 1 to pin 3.
In general, to move n discs from pin 1 to pin 3 using pin 2 as an intermediary, you first need to move the top n –
1 discs from pin 1 to pin 2 using pin 3 as intermediary.

The following algorithm can be used to move the top n discs from the first pin START to final pin FINISH
through the temporary pin TEMP:-

Move (n, START, TEMP, FINISH)


1. When n = 1:
a. MOVE a disc from START to FINISH
b. Return
2. Move the top n -1 discs from START to TEMP using FINISH as an intermediary [MOVE (n - 1, START,
FINISH, TEMP)]
3. Move the top disc from START to FINISH
4. Move the top n – 1 discs from TEMP to FINISH using START as an intermediary [MOVE (n - 1, TEMP,
START, FINISH)]
In general, this solution requires 2n-1 moves for n discs.
Structured Programming

 In 1966, computer scientists Corrado Böhm and Giuseppe Jacopini demonstrated that all programs
could be written using three control structures: Sequence, Selection, and Repetition.
 The sequence structure is the construct where one statement is executed after another.
 The selection structure is the construct where statements can executed or skipped depending on whether
a condition evaluates to TRUE or FALSE.
o There are three selection structures in C:
1. IF
2. IF – ELSE
3. SWITCH
 The repetition structure is the construct where statements can be executed repeatedly until a condition
evaluates to TRUE or FALSE
o There are three repetition structures in C:

10
1. WHILE
2. DO – WHILE
3. FOR

What is Pseudocode

Pseudocode is the plain English representation of a computer program or algorithm, which specifies the flow
and operation of the program. It is generally used to represent the structural flow of a program, and it is not
associated with any specific programming language. The same quality makes it a perfect tool to represent
algorithms for various problems. Some significant points you need to know about pseudocode are:
 It is not a programming language.
 It is just a learning and reasoning tool, which is used by programmers and developers to underline how
to write the actual code.
 Pseudocode cannot be executed or compiled by any compiler , interpreter , or assembler.
 Unlike programming language code, pseudocode does not follow a strict structure and syntax. Here, the
programmer can write the code syntax as he pleases.

Advantages of Pseudocode

 Improves the readability of any approach. It’s one of the best approaches to start implementation
of an algorithm.
 Acts as a bridge between the program and the algorithm or flowchart. Also works as a rough
documentation, so the program of one developer can be understood easily when a pseudo code is
written out. In industries, the approach of documentation is essential. And that’s where a pseudo-
code proves vital.
 The main goal of a pseudo code is to explain what exactly each line of a program should do, hence
making the code construction phase easier for the programmer.

How to write a Pseudo-code?

1. Arrange the sequence of tasks and write the pseudocode accordingly.


2. Start with the statement of a pseudo code which establishes the main goal or the aim.
3. Use appropriate naming conventions. The human tendency follows the approach to follow what we
see. If a programmer goes through a pseudo code, his approach will be the same as per it, so the
naming must be simple and distinct.
4. Use appropriate sentence casings, such as CamelCase for methods, upper case for constants and
lower case for variables.

11
5. Elaborate everything which is going to happen in the actual code. Don’t make the pseudo code
abstract.
6. Use standard programming structures such as ‘if-then’, ‘for’, ‘while’, ‘cases’ the way we use it in
programming.
7. Check whether all the sections of a pseudo code is complete, finite and clear to understand and
comprehend.
Don’t write the pseudo code in a complete programmatic manner. It is necessary to be simple to understand
even for a layman or client, hence don’t incorporate too many technical terms.

Why Use Pseudocode?

Before building anything, we first need to create a blueprint that describes all the methods, strategies, flow of
the structure, and the resulting interface of the actual project. Developers and programmers follow the same
concept before they start writing the code for their projects, but here instead of the blueprint, the developer uses
pseudocode to represent what approach and structure the actual program will follow. The syntax of every
programming language varies, which makes it hard to understand the implemented algorithm by studying the
code. But pseudocode provides a solution for this. With the help of pseudocode, we can write an algorithm
using simple English. It allows a specific programming language developer or programmer could to understand
the logic of the program and implement it in a specific programming language. With pseudocode, we deal with
the actual logic and the basic operations provided by every programming language . While writing pseudocode,
we focus on the atomic process and methods provided by every programing language, and based on those
operations and methods we try to build an algorithm. When we write pseudocode for an algorithm, there are
several operations, operators, and methods that we can use.
Difference between Algorithm and Pseudocode
BASIS OF COMPARISION ALGORITHM PSEUDOCODE
Description Algorithm is a well-defined sequence of A Pseudocode is one of the methods
steps that provides a solution for a given that can be used to represent an
problem. algorithm.
Writing Algorithms are generally written in a Pseudocode is written in a format
natural language or plain English that is similar to the structure of a
language. high-level programming language.
Nature It is a systematic and a logical approach, It is a simpler version of coding in a
where the procedure is defined step- programming language.
wise.
Construction Algorithm is difficult to debug and Pseudocode is easy to construct and
construct. debug.
Understandability It is difficult to understand and interpret.
Pseudocode is easy to understand and
interpret.
Formats Algorithm can be represented using There are many formats that could be
natural language, flowchart and so on. used to write pseudocodes.
Construction Rules There are no rules to follow while Certain rules are followed while
constructing it. constructing it. Control structures
such as ‘while’, ‘if-then-else’,
12
‘repeat-until’, and so on can be used.
Programming Algorithms can be used in any complex Pseudocodes are not used in any
programming language as it uses simple complex programming languages.
logical code snippets.
Outlook Algorithms can be considered as Pseudocodes cannot be considered as
pseudocodes. algorithms.

Flowcharts
A flowchart is a graphical representation of the sequence of operations in a program. It uses boxes of different
shapes to denote different types of instructions. The actual instructions are written within these boxes using
clear and concise statements.

Flowchart symbols: Only a few symbols are needed to indicate the necessary operations in flowchart.

Deci
Processing Input/Output Terminal
sion

Data flow Connectors

Terminal: The terminal symbol indicates the beginning (start), end (stop) in a program’s logic flow.

Input/Output: The input/output symbol denotes any function of an input/output nature in a program.

Processing: A processing symbol represents arithmetic and data movement instructions.

Decision: The decision symbol indicates a decision point, that is, a point at which a branch to one of two or
more alternative points is possible.

Flow Lines: Flow lines with arrowheads indicate the flow of operation, that is, the exact sequence in which the
instructions are executed.

Connectors: Whenever a flowchart becomes so complex that the number and direction of flow lines are
confusing, or it spreads over more than one page, it is useful to utilize connector symbols as a substitute for
flow lines.

DETERMINING THE EFFICIENCY OF AN ALGORITHM

The greatest difficulty in solving programming problems is not how to solve the problem, but how to solve the
problem efficiently. Factors that affect the efficiency of a program include the speed of the machine, the
compiler. The operating system, the programming language, and the size of the input. However, in addition to

13
these factors, the way data of a program is organized, and the algorithm used to solve the problem also has a
significant impact on the efficiency of a program.

There can be cases, where a number of methods and algorithms can be used to solve a problem. In such a
situation, it can be difficult to decide which algorithm to use.

When there are several different ways to organize data and devise algorithms, it becomes important to develop
criteria to recommend a choice. Therefore, you need to study the behavior of algorithms under various
conditions and compare their efficiency.

The efficiency of an algorithm can be computed by determining the amount of resources it consumes. The
primary resources that an algorithm consumes are:

 Time: The CPU time required to execute the algorithm


 Space: The amount of memory used by the algorithm for execution. The lesser resources that an
algorithm uses, the more efficient it is.

TIME/SPACE TRADEOFF in Algorithm

To solve a given programming problem, many different algorithms may be used. Some of these algorithms may
be extremely time-efficient and others extremely space-efficient.

Time/space tradeoff refers to a situation where you can reduce the use of memory at the cost of slower program
execution, or reduce the running time at the cost of increased memory usage.

An example of a situation where a time/space tradeoff can be applied is that of data storage. If data is stored in a
compressed form, the memory usage is less because data compression reduces the amount of space required.
However, it is more time consuming because some additional time is required to run the compression algorithm.
Similarly, if data is stored in its uncompressed form, the memory usage is more, but the running time is less.

Memory is generally perceived to be extensible because you can increase the memory of your computer. Time,
however, is not extensible. Therefore, time considerations generally override memory considerations.

METHOD FOR DETERMINING EFFICIENCY

Although, the efficiency of an algorithm depends on how efficiently it uses time and memory space, the scope
of this course is limited to determining only the time efficiency of an algorithm.

To measure the time efficiency of an algorithm, you can write a program based on the algorithm, execute it, and
measure the time it takes to run. The execution time that you measure in this case would depend on a number of
factors such as:-

14
 Speed of the machine
 Compiler
 Operating System
 Programming language
 Input data

However, to determine how efficiently an algorithm solves a given problem, you would like to determine how
the execution time is affected by the nature of the algorithm. Therefore, you need to develop fundamental laws
that determine the efficiency of a program in terms of the nature of the underlying algorithm.

To understand how the nature of an algorithm affects the execution, consider a simple example. Suppose
assignment, comparison, write, and increment statements take a, b, c, and d time units to execute respectively.
Now, consider the following code used to display the elements stored in an array: -

1. Set I = 0 // 1 assignment
2. While(I < n): // n comparisons
a. Display a[I] // n writes
b. Increment I by 1 // n increments
The execution time required for the preceding algorithm is given by:-
T=a+bxn+cxn+dxn
T = a + n(b + c + d)
Here, T is the total running time of the algorithm expressed as a linear function of the number of elements (n) in
the array. From the preceding expression, it is clear that T is directly proportional to n. In fact, the total running
time T is directly proportional to the number of iterations involved in the algorithm. The number of iterations
can be determined by counting the number of comparisons involved in the algorithm. In the preceding code
segment, a total of n comparisons are being made. Therefore, the total running time of the algorithm, T is
directly proportional to n. As T is directly proportional to n, an increase in the value of n will result in a
proportional increase in the value of T, as shown in the following figure.

15
From the preceding discussion, you can conclude that the running time of a program is a function of n, where n
is the size of the input data. The rate at which the running time of an algorithm increases as a result of an
increase in the volume of input data is called the order of growth of the algorithm.

Analysis of Algorithms
Algorithm analysis is an important part of computational complexities. The complexity theory provides the
theoretical estimates for the resources needed by an algorithm to solve any computational task. Analysis of the
algorithm is the process of analyzing the problem-solving capability of the algorithm in terms of the time and
size required (the size of memory for storage while implementation). However, the main concern of the analysis
of the algorithm is required time or performance.
Complexities of an Algorithm
The complexity of an algorithm computes the amount of time and spaces required by an algorithm for an input
of size (n). The complexity of an algorithm can be divided into two types. The time complexity and the space
complexity.
Time Complexity of an Algorithm
The time complexity is defined as the process of determining a formula for total time required towards the
execution of that algorithm. This calculation is totally independent of implementation and programming
language.
Space Complexity of an Algorithm
Space complexity is defining as the process of defining a formula for prediction of how much memory space is
required for the successful execution of the algorithm. The memory space is generally considered as the primary
memory.
Big O Notations

The order of growth of an algorithm is defined by using the big O notation. The big O notation has been
accepted as a fundamental technique for describing the efficiency of an algorithm.
The following table lists some possible orders of growth, and their corresponding big O notations.
Order of Growth Big O notation
Constant O(1)
Logarithmic O(log n )
Linear O(n)
Loglinear O(n log n )
Quadratic O(n2)
Cubic O(n3)
Exponential O(2n), O(10n)

If an algorithm has a linear order of growth, the algorithm is said to be of the order O(n). Similarly, if an
algorithm has a quadratic order of growth, the algorithm is said to be of the order O(n2).
Selecting an Efficient Algorithm

16
Now that you know how the efficiency of a particular algorithm is determined, let us see how this knowledge
can be used to select an efficient algorithm. According to their orders of growth, the big O notations can be
arranged in an increasing order as:-

O(1) < O(log n) < O(n) < O(n log n) < O(n2) < O(n3) < O (2n) < O (10n) Therefore, if a problem can be solved
by using algorithms each of the preceding orders of growth, an algorithm of the order of O(1) will be considered
best, and an algorithm of the order O(10n) will be considered the worst. The goal of algorithm development
should be to make algorithms of the smallest possible orders.

The following table depicts the orders of growth for the preceding big O notations.
Big O Notation Order of growth

O(1)

O(log n)

O(n)

17
O(n log n)

O(n2)

O(n3)

O(2n)

18
O(10n)

Now, consider that the assignment, comparisons, write and increment statements take a,b,c and d time units to
execute, respectively. Also, suppose all arithmetic operations require e time units to execute. Now, consider the
following two algorithms to find the sum of first n natural numbers: -
Algorithm A
1. Set sum = 0 // 1 assignment
2. Set i = 0 // 1 assignment
3. While (i <= n) // n comparisons
a. Set sum = sum + i // n arithmetic operations, n assignments
b. Increment i by 1 // n increments
4. Display (sum) // 1 write

The execution time requires for Algorithm A is given by: -


T = (n + 2) x a + (n x b) + (1 x c) + (n x d) + (n x e)
T = an + 2n + bn + c + dn + en
T = c + n(a + b + d + e + 2)
As T is a linear function of n.
Therefore, the algorithm is of the order O(n).
Algorithm B
1. Set sum = (n x (n + 1))/2 // 3 arithmetic operations, 1 assignment
2. Display (sum) // 1 write

Both Algorithm A and Algorithm B perform the same task, that is, both determine the sum of the first n natural
numbers. Algorithm A adds each number iteratively to a variable sum. However, Algorithm B uses a formula to
calculate the sum of the first n natural numbers.

Now determine the time required to execute algorithm B:-


T = (1 x a) + (1 x c) + (3 x e)
T = a + c + 3e

Unlike Algorithm A, the time taken by Algorithm B is a constant, and does not depend on the value of n.
Therefore, the algorithm is of the order O(1). Because Algorithm A is of the order O(n), the execution time of
Algorithm A increases linearly with the value of n. However, Algorithm B is of the order O(1). Therefore, the
19
execution time of Algorithm B is constant. This means that an increase in the value of n does not have any
impact on the execution time of the algorithm. Therefore, however large the problem be, Algorithm A solves it
in the same amount of time.

Suppose for n = 10, both Algorithm A and B take 10 nanoseconds(ns) to execute. However when n is increased
to 100, Algorithm A will take 100 ns to execute, but Algorithm B will take only 10 ns to execute, Similarly,
when n is increased to 1000, Algorithm A will take 1000 ns to execute, but Algorithm B will take only 10 ns.
This means that when the problem is very large in size, Algorithm B would prove to be much more efficient
than Algorithm A.

Reserved Words / Keywords

There are certain words that are reserved for doing specific tasks. These words are known as keywords and they
have standard, predefined meaning in C. They are always written in lowercase. There are only 32 keywords
available in C which are given below-

auto default
break do
case double
char else
const enum
continue extern
float
for
goto
if
int
long
register
return
short
signed
sizeof
static
struct
switch
typedef
union
unsigned
void
volatile
while

20
Identifiers

All the words that we will use in our C programs will be either reserve words or identifiers. Reserve words are
predefined and can’t be changed by the user, while identifiers are used defined words and used to give names to
entities like variables, arrays, functions, structure etc.

Rules for naming identifiers are given-below-

1. The name should consist of only alphabets (both upper and lower case), digits and underscore sign (_).
2. First character should be an alphabet or underscore.
3. The name should not be keyword.
4. Since C is case sensitive, the uppercase and lowercase letters are considered different. For example
code, Code, CODE are three different identifiers.
5. An identifier name may be arbitrarily long. Some implementations of C recognize only the first eight
characters, though most implementations recognize 31 characters. ANSI standard compilers recognize
31 characters.

Data Types

C supports different type of data. Storage representation of these data types is different in memory. There are
four fundamental datatypes in C, which are int, char, float and double.

‘char’ is used to store any single character, ‘int’ is used to store integer value, ‘float’ is used for storing single
precision floating point number and ‘double’ is used for storing double precision floating point number.

The size and range of different data types on a 16-bit machine is given in the following table. The size and
range may vary on machines with different word sizes.

Basic data types Data types with type Size (bytes) Range
qualifiers
char char or singed char 1 -128 to 127
unsigned char 1 0 to 255
int int or signed int 2 -32768 to 32767
unsigned int 2 0 to 65535
float float 4 3.4E-38 to 3.4E+38
double double 8 1.7E-308 to 1.7E+308
long double 10 3.4E-4932 to 1.1E+4932

Constants

Constant is a value that cannot be changed during execution of the program. There are three types of constants-

Constants

Numeric constant Character constant String constant


21
Integer constant Real constant

Decimal Octal Hexadecimal

Numeric Constants

Numeric constants consist of numeric digits, they may or may not have decimal point (.). These are the rules for
defining numeric constants-

i. Numeric constant should have at least one digit.


ii. No comma or space is allowed within the numeric constant.
iii. Numeric constants can either be positive or negative but default sign is always positive.

There are two types of numeric constants-

 Integer constant

Integer constants are whole numbers which have no decimal point (.). There are three types of integer constants
based on different number systems. The permissible characters that can be used in these constants are-

Decimal constants- 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 (base 10)

Octal constants- 0, 1, 2, 3, 4, 5, 6, 7 (base 8)

Hexadecimal- 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E, F, a, b, c, d, e, f (base 16)

 Real (floating point) constant

Floating point constants are numeric constants that contain decimal point.

For expressing very large or very small real constants, exponential form is used. Here the number is written in
the mantissa and exponent form, which are separated by ‘e’ or ‘E’. The mantissa can be an integer or a real
number, while the exponent can be only an integer (positive or negative). For example the number 1800000 can
be written as 1.8e6, here 1.8 is mantissa and 6 is the exponent.

Character Constants

A character constant is a single character that is enclosed within single quotes. Some valid character constants
are-

‘9’ ‘D’ ‘$’ ‘‘ ‘#’

Every character constants has a unique integer value associated with it. This integer is the numeric vale of the
character in the machine’s character code. If the machine is using ASCII (American Standard Code of
Information Interchange), then the character ‘G’ represents integer value 71 and the character ‘5’ represents
value 53.

Some ASCII value are-

22
A–Z ASCII value (65 – 90)

a–z ASCII value (97 – 122)

0–9 ASCII value (48 – 57)

; ASCII value (59)

String Constants

A string constant has zero, one or more than one character. A string constant is enclosed within double quotes (“
“). At the end of string, \0 is automatically placed by the compiler.

Note that “A” and ‘A’ are different, the first one is a string constant which consists of character A and \0 while
the second one is a character constant which represents integer value 65.

Symbolic Constants

If we want to use a constant several times then we can provide it a name. For example if we have to use the
constant 3.14159265 at many places in our program, then we can give it name PI and use this name instead of
writing the constant value anywhere. These constants are called symbolic constants or name constants.

A symbolic constant is a name that substitutes for a sequence of characters. The characters may represent a
numeric constant, a character constant or a string constant.

These constants are generally defined at the beginning of the program as-

#define name value

Here ‘name’ is the symbolic name for the constant, and generally written in uppercase letters. ‘value’ can be
numeric, character or string constant.

For example:

#define MAX 100

#define PI 3.14159265

#define CH ‘y’

#define NAME “Suresh”

In the program, these names will be replaced by the corresponding values. These symbolic constants improve
the readability and modifiability of the program

Variables

Variable is name that can be used to store values. Variables can take different values but one at a time. These
values can be changed during the execution of the program. A data type is associated with each variable. The
data type of the variable decides what values it can take. The rules for naming variables are same as that for
naming identifiers.

Declaration of Variables

23
It is must to declare a variable before it is used in the program. Declaration of a variable specifies its name and
data type. The type and range of values that a variable can store depends upon its data type.

The syntax of declaration of variable is-

datatype variablename;

here datatype may be int, float, char, double etc. some example of declaration of variables are-

int x;

float salary;

char grade;

Here x is a variable of type int, salary is variable of type float and grade is variable of type char.

We can also declare more than one variable in single declaration. For example-

int x, y, z, total;

Here x, y, z, total are all variables of type int.

Initialisation of Variables

When a variable is declared it contains undefined vale commonly known as garbage value. If we want we can
assign some initial value to the variable during the declaration itself, this is called initialisation of the variable.
For example-

int a = 5;

float x = 8.9, y = 10.5;

Control Statements

In C programs, statements are executed sequentially in the order in which they appear in the program. But
sometimes we may want to use a condition for executing only a part of program. Also many situations arise
where we may want to execute some statements several times. Control statements enable us to specify the order
in which the various instructions in the program are to be executed. This determines the flow of control. Control
statements define how the control is transferred to other parts of the program. c language supports four types of
control statements, which are as-
1. if …else
2. goto
3. switch
4. loop
o while
o do…while
o for
1. if…else
This is a bi-directional conditional control statement. This statement is used to test a condition and take one of
the two possible actions. If the condition is true then a single statement or a block of statements is executed (one

24
part of the program), otherwise another single statement or a block of statements is executed (other part of the
program). Recall that in C, any nonzero value is regarded as true while zero is regarded as false.

Syntax 1:
if (condition) if (condition)
statements 1; {
statement;
……….
………..
}

There can be a single statement or a block of statements after the if part.

True
Conditio
n

Statement 1
False

Next Statement

Flow chart of if control statement

Here if the condition is true(nonzero) then statement1 is executed, and if it is false(zero), then the next statement
which is immediately after the if control statement is executed.

Syntax 2:

if (condition) if (condition)

statement1; {

else statement;

statement2; ………..

else

statement;

………..
25
}

True False
Conditi
on

Statement 1 Statement 2

Next Statement

Flow chart of if…else control statement

Here if the condition is true then statement1 is executed and if it is false then statement2 is executed. After this
the control transfers to the next statement which is immediately after the if..else control statement.

2. Nesting if….else

We can have another if..else statement in the if block or the else block. This is called nesting of if..else
statements. Here is an example of nesting where we have if..else inside both if block and else block.

if (condition 1)

if (condition 2)

statementA1;

else

statementA2;

else

if (condition 3)

statementB1;

26
else

statementB2;

While nesting if…else statements, sometimes confusion may arise in associating else part with appropriate if
part. Let us take an example-

if (grade = = ‘A’)

if (marks > 95)

printf(“Excellent”);

else

printf(“work hard for getting A grade”);

If we write the above code without braces as-

if (grade = = ‘A’)

if (marks > 95)

printf(“Excellent”);

else

printf(“work hard for getting A grade”);

Here the else part is matched with the second if, but we wanted to match it with the first if. The compiler does
not associate if and else parts according to the indentations, it matches the else part with closest unmatched if
part. So whenever there is doubt regarding matching of if and else parts we can use braces to enclose each if and
else blocks.

3. Loops

Loops are used when we want to execute a part of the program or a block of statements several times. For
example, suppose we want to print “C is the best” 10 times. One way to get the desired output is- we write 10
printf statements, which is not preferable. Other way out is – use loop. Using loop we can write one loop
statement and only one printf statement, and this approach is definitely better than the first one. With the help of
loop we can execute a part of the program repeatedly till some condition is true. There are three loop statements
in C-

i. while
ii. do..while
iii. for
i. while loop
27
The while statement can be written as:

while (condition) while (condition)

statement; {

statement;

statement;

………

False
While(conditio
n)

True

Body of loop

Next statement
Flow chart of while loop Out of loop

Like if-else statement here also we can have either a single statement or a block of statements, and here it is
known as the body of loop. Now let’s see how this loop works.

First the condition is evaluated; if it is true then the statements in the body of loop are executed. After the
execution, again the condition is checked and if it is found to be true then again the statements in the body of
loop are executed. This means that these statements are executed continuously till the condition is true and
when it becomes false, the loop terminates and the control comes out of the loop. Each execution of the loop
body is known as iteration.

ii. do…while loop

The ‘do…while’ statement is also used for looping. The body of this loop may contain a single statement or a
block of statements. The syntax for writing this loop is:

do do

statement; {

28
while(condition); statement;

statement;

………..

}while (condition);

Body of loop

False
Conditio
n

True
Next statement
Out of loop
Flow chart of do…while loop

Here firstly the statements inside the loop body are executed and then the condition is evaluated. If the
condition is true, then again the loop body is executed and this process continues until the condition becomes
false. Note that unlike while loop, here a semicolon is placed after the condition.

In a ‘while’ loop, first the condition is evaluated and then the statements are executed whereas in a do while
loop, first the statements are executed and then the condition is evaluated. So if initially the condition is false
the while loop will not execute at all, whereas the do while loop will always execute at least once.

iii. for loop

The ‘for’ statement is very useful while programming in C. It has three expressions and semicolons are used for
separating these expressions. The ‘for’ statement can be written as-

for (expression1; expression2; expression3) for (expression1; expression2; expression3)

statement; {

statement;

statement;

……..

The loop body can be a single statement or block of statements.

29
Expression1 is an initialization expression, expression2 is a test expression or condition and expression3 is an
update expression. Expression1 is executed only once when the loop starts and is used to initialize the loop
variables. This expression is generally an assignment expression. Expression2 is a condition and is tested before
each iteration of the loop. This condition generally uses relational and logical operators. Expression3 is an
update expression and is executed each time after the body of the loop is executed.

Initialization expression

False
Conditio
n
True

Body of loop

Update expression

Next statement
Out of loop
Flow chart of for loop

The work done by the for loop can be performed by writing a while loop as-

expression 1;

while (expression 2)

Statement;

……

…..

Expression 3;

Although the task of while and for loops is same, the for loop is generally used when the number of iterations
are known in advance and while loop is used where number of iterations are not known.

30

You might also like