1 Lecture 1
1 Lecture 1
of Algorithms
CS-332
(3-0-3)
Books / Reference Materials:
Textbook:
1. Introduction to Algorithms, Cormen, T. H.,Leiserson, C.E., Rivest, R.L.&
Stein, C., 4th Edition (2009), MIT Press.
Reference Books:
2. An Introduction to the Analysis of Algorithms, Sedgewick, R.& Flajolet,
P., 2nd Edition (2012), Addison-Wesley.
3. Foundation of Algorithms Using C++ Pseudocode, Neapolitian, R., 6th
Edition (2013), Jones & Bartlett Learning.
4. Introduction to the Design and Analysis of Algorithms, Levitin, A., 3rd
Edition (2012), Pearson
Course Objectives
2) Output
At least one quantity is produced.
Algorithms
must satisfy 3) Definiteness
Each instruction of the algorithm
the following should be clear and unambiguous.
criteria 4) Finiteness
The process should be terminated
after a finite number of steps.
5) Effectiveness
Every instruction must be basic
enough to be carried out theoretically
or by using paper and pencil.
Properties of Algorithm
Non-Ambiguity
Each step in an algorithm should be non-ambiguous. That means each instruction should be
clear and precise. The instruction in any algorithm should not denote any conflicting
meaning.
Range of Input
The range of input should be specified. This is because normally the algorithm is input driven
and if the range of input is not being specified then an algorithm can go into an infinite state.
Multiplicity
The same algorithm can be represented in several different ways. That means we can write
in simple English the sequence of instruction, or we can write it in form of pseudo code.
Similarly, for solving the same problem we can write several different algorithms.
Speed
The algorithm is written using some specified ideas. But such an algorithm should be
efficient and should produce the output with fast speed.
Finiteness
The algorithm should be finite. That means after performing required operations it should be
terminated.
Fundamentals of Algorithmic
Problem Solving
Understanding the Problem
Ascertaining the capabilities of a computational Design
Choosing between exact and approximate problem
solving
Algorithm Design Techniques
Designing an appropriate data structure
Method of specifying an algorithm
Proving an Algorithm’s correctness
Analyzing an algorithm
Coding an algorithm
Fundamenta
ls of
Algorithmic
Problem
Solving
Preconditions and Postconditions
Preconditions and Postconditions
// Precondition: x >= 0.
// Postcondition: The square root of x has
// been written to the standard output.
• In this example, the
precondition requires that
x >= 0
}
Example: The Graph Search Algorithm
• visit v //retrieve and remove edge e
• put all of the edges that leave v from the dispenser
into the dispenser • let w be the head of e
// Precondition: • if w has not been visited
// v is visited. Every other vertex • visit e
in the graph is unvisited. • visit w
// Every edge in the graph that put all of the edges that
goes from v to another vertex is in leave w into the dispenser
the dispenser.
• endif
• while the dispenser is not empty
• endwhile
// Invariant:
// Postcondition:
// Every edge in the graph that
goes from a visited vertex to an // If there is a directed path from
unvisited vertex is in the dispenser. v to a vertex x then x has been
visited.
Example
struct Node { // SINGLY-linked list
int value;
struct Node* next;
};
// Insert a new node with the given value before an existing node.
// If the list is empty, create a new node, which becomes the
head.
void insert_after(struct Node* existing, int value, struct Node** a_head)
{ // … }
// Create a list with the numbers from start to stop. Return the
head.
struct Node* create_count_list(int start, int stop) {
struct Node* head = NULL; // start as empty list
struct Node* tail = NULL;
for(int value = start; value <= stop; value++) {
insert_after(tail, value, &head);
tail = tail -> next;
Loop Invariant
Loop Invariant Condition with Examples
• A loop invariant is a condition that is true at the beginning and end of
every loop iteration.
• The concept is similar to a class invariant, which must be true at the
beginning and end of every public method.
• A loop invariant is some predicate (condition) that holds for every loop
iteration.
• When you write a loop that works correctly, you are at least implicitly
relying on a loop invariant.
• For example, let’s look at a simple for loop that looks like this:
int j = 9;
for(int i=0; i<10; i++)
j--;
A good loop invariant should
satisfy three properties:
• Initialization: The loop invariant must be true before the first
execution of the loop.
• Maintenance: If the invariant is true before an iteration of
the loop, it should be true also after the iteration.
• Termination: When the loop is terminated the invariant
should tell us something useful, something that helps us
understand the algorithm.
On the other hand, the loop conditional must be false after the
loop terminates, otherwise, the loop would never terminate.
A good loop invariant should
satisfy three properties:
Loop Invariant:
• max is the maximum value in a[0…i-1]
Initialization
•i=1 and the scope of the array is a[0…i-
1]=a[0..1-1]=a[0], max = a[0]
•Thus, invariant holds
Maintenance:
•Assuming loop invariant holds at iteration k, then
max is the maximum value in a[0..k-1]
•In the next iteration k=1, the code compares and
possibly updates max with a[k], max is the
maximum value in scope a[0..k]
•Thus, invariant holds
Termination
• i=len(a), max is the maximum value in
a[0..len(a)-1]
• Thus, invariant holds
Asymptotic Analysis
Sorting
Algorithms
Insertion
Sort
Key
Questions
●
How do you fi nd effi cient
solutions to seemingly hard
problems?
●
How do you prove that an
a l g o r i t h m is correct?
●
How do you analyze an
algorithm’s runtime?
Insertion Sort
• Idea: like sorting a hand of playing cards
• Start with an empty left hand and the cards facing
down on the table.
• Remove one card at a time from the table, and insert
it into the correct position in the left hand
• compare it with each of the cards already in the
hand, from right to left
• The cards held in the left hand are sorted
• these cards were originally the top cards of the
pile on the table
25
Insertion Sort
12
26
Insertion Sort
6 10 24 36
12
27
Insertion Sort
6 10 24 3
6
12
28
Insertion Sort
input array
5 2 4 6 1
3
at each iteration, the array is divided in two sub-arrays:
sorted unsorted
29
Insertion Sort
30
Another Example
31
Insertion Sort
7 4 2 1 6
Insertion Sort
7 4 2 1 6
Insertion Sort
7 4 2 1 6
Insertion Sort
7 4 2 1 6
Insertion Sort
4 7 2 1 6
Insertion Sort
4 7 2 1 6
Insertion Sort
4 7 2 1 6
Insertion Sort
4 7 2 1 6
Insertion Sort
4 2 7 1 6
Insertion Sort
4 2 7 1 6
Insertion Sort
2 4 7 1 6
Insertion Sort
2 4 7 1 6
Insertion Sort
2 4 7 1 6
Insertion Sort
2 4 7 1 6
Insertion Sort
2 4 1 7 6
Insertion Sort
2 4 1 7 6
Insertion Sort
2 1 4 7 6
Insertion Sort
2 1 4 7 6
Insertion Sort
1 2 4 7 6
Insertion Sort
1 2 4 7 6
Insertion Sort
1 2 4 7 6
Insertion Sort
1 2 4 7 6
Insertion Sort
1 2 4 6 7
Insertion Sort
1 2 4 6 7
INSERTION-SORT
Alg.: INSERTION-SORT(A) 1 2 3 4 5 6 7 8
for j ← 2 to n a1 a2 a3 a4 a5 a6 a7 a8
do key ← A[ j ] key
Insert A[ j ] into the sorted sequence A[1 . . j -1]
i←j-1
while i > 0 and A[i] > key
do A[i + 1] ← A[i]
i←i–1
A[i + 1] ← key
• Insertion sort – sorts the elements in place
56
Loop Invariant for Insertion Sort
Alg.: INSERTION-SORT(A)
for j ← 2 to n
do key ← A[ j ]
Insert A[ j ] into the sorted sequence A[1 . . j -1]
i←j-1
while i > 0 and A[i] > key
do A[i + 1] ← A[i]
i←i–1
A[i + 1] ← key
Invariant: at the start of the for loop the elements in A[1 . . j-1]
are in sorted order
57
Analysis of Insertion Sort
INSERTION-SORT(A) cost
for j ← 2 to n times
do key ← A[ j ] c1 n
Insert A[ j ] into the sorted sequence A[1 . . j -1] c2 n-1
i←j-1 0 n-1
n-1
n
t
while i > 0 and A[i] > key c4 j 2 j
(t 1)
n
do A[i + 1] ← A[i] c5 j 2 j
(t 1)
n
i←i–1 c6
j 2 j
A[i + 1] ← key
c7
tj: # of times the while statement is executed at iteration j
n n c
n 8 n-
T (n) c1n c2 (n 1) c4 (n 1) c5 t j c6 t j 1 c7 1t j 1 c8 (n 1)
j 2 j 2 j 2
58
Best Case Analysis
• The array is already sorted “while i > 0 and A[i] > key”
• A[i] ≤ key upon the first time the while loop test is run
(when i = j -1)
• tj = 1
+ c5 + c8) n n n
T (n) c1n c2 (n 1) c4 (n 1) c5 t j c6 t j 1 c7 t j 1 c8 (n 1)
j 2 j 2 j 2
= an + b = (n) 59
Worst Case Analysis
• The array is in reverse sorted order “while i > 0 and A[i] > key”
• Always A[i] > key in while loop test
• Have to compare key with all elements to the left of the j-th position
compare with j-1 elements tj = j
n
n(n 1) n
n(n 1) n
n(n 1)
using j 1
j
2
j
j 2 2
1 ( j 1)
j 2 2
we have:
n( n 1) n( n 1) n( n 1)
T ( n ) c1n c2 ( n 1) c4 ( n 1) c5 1 c6 c7 c8 ( n 1)
2 2 2
INSERTION-SORT(A) cost
for j ← 2 to n times
do key ← A[ j ] c1 n
• Advantages
• Good running time for “almost sorted”
arrays (n)
• Disadvantages
• (n2) running time in worst and average
case
• n2/2 comparisons and exchanges
66