DS_class_ppts(Searching,Sorting to AVLtrees) (1)
DS_class_ppts(Searching,Sorting to AVLtrees) (1)
Internal External
THREE INTERNAL SORTS.
Selection sort
Shell sort
Bubble sort
SORT ORDER.
Data may be sorted in either ascending or descending
sequence.
input
order
output
PASSES.
During the sorting process, the data are traversed
many times. Each traversal of the data is referred
to as a sort pass.
Example 2
INSERTION SORT.
✘ Given a list, it is divided into two parts: sorted and
unsorted.
✘ In each pass the first element of the unsorted sublist is
transferred to the sorted sublist by inserting it at the
appropriate place.
✘ If list has n elements, it will take at most n – 1 passes to
sort the data.
INSERTION SORT.
BUBBLE SORT.
When the pivot element is placed in (k-1)th position, it will be the kth
smallest element
When the pivot element is placed in (n-k)th position, it will be the kth
largest element
QUICK SORT ALGORITHM.
✘ Two Algorithms:
- Quick Sort Recursive
- Partition
QUICK SORT EXAMPLES. (PARTITIONS)
QUICK SORT EXAMPLES.
QUICK SORT EXAMPLES. Pivot Element = 6
QUICK SORT ALGORITHM.
Algorithm Quicksort (Array, Low, High)
1. If (Low < High) Then
1. Set Mid = Partition (Array, Low, High)
2. Quicksort (Array, Low, Mid – 1)
3. Quicksort (Array, Mid + 1, High)
2. End
QUICK SORT ALGORITHM.
Algorithm Partition (Array, Low, High)
1. Set Key = Array[low], I = Low + 1, J = High
2. Repeat Steps A through C
A. while (I < High && Key ≥ Array[i]) i++
B. while (Key < Array[j]) j- -
C. if (I < J) then
swap Array[i] with Array[j]
else
swap Array[low] with Array[j]
return j {Position For KEY}
3. End
DIVIDE & CONQUER.
✘ Divide-and conquer is a general
algorithm design paradigm.
✘ Divide: divide the input data S in two
disjoint subsets S1 and S2.
✘ Recur: solve the subproblems
associated with S1 and S2.
✘ Conquer: combine the solutions for S1
and S2 into a solution for S.
✘ Base case for recursion are subproblems
of size 0 or 1.
MERGE SORT.
✘ Invented by John von Neumann in 1945, example of Divide &
Conquer.
✘ Repeatedly divides the data in half, sorts each half, and combines the
sorted halves into a sorted whole.
✘ Basic algorithm:
- Divide the list into two roughly equal halves.
- Sort the left half.
- Sort the right half.
- Merge the two sorted halves into one sorted list.
✘ Often implemented recursively
✘ Runtime: O(n log n).
MERGE SORT ALGORITHM.
Algorithm merge(S1, S2, S)
Input: Two arrays S1 & S2 of size n1 and n2 sorted in
Algorithm mergeSort(S) non decreasing order and an empty array S of
size at least (n1+n2)
Input: Sequence S with n elements Output: S containing elements from S1 & S2 in sorted order.
i1
Output: Sequence S sorted j1
if S.size() > 1 while (i ≤ 𝑛1) 𝑎𝑛𝑑 (𝑗 ≤ n2)
if S1[i] ≤ S2[j] then
(S1, S2) partition(S, n/2) S[i+j-1] Si[i]
i i +1
mergeSort(S1) else
S[i+j-1] Si[j]
mergeSort(S2)
j j +1
S merge(S1, S2) while ((i ≤ 𝑛1) 𝑑𝑜
S[i+j-1] Si[i]
i i +1
while (𝑗 ≤ n2)
S[i+j-1] Si[j]
j j +1
Merge Sort
example.
split
22 18 12 -4 58 7 31 42
split split
22 18 12 -4 58 7 31 42
split split split split
22 18 12 -4 58 7 31 42
merge merge merge merge
18 22 -4 12 7 58 31 42
merge merge
-4 12 18 22 7 31 42 58
merge
-4 7 12 18 22 31 42 58
Merge Sort
example.
SEARCHING.
✘ One MORE common and time-consuming operations in
computer science is searching
✘ The process used to find the location of a target among a
list of objects.
✘ The two basic search algorithms:
✘ Sequential search including three interesting variations
and,
✘ Binary search.
SEQUENTIAL SEARCH.
✘ Used whenever the list is not ordered.
✘ Generally, technique used only for small lists or lists that are not
searched often.
✘ Process: Start searching for the target at the beginning of the list and
continue until target found or it is not in the list.
✘ This approach has two possibilities: Find element (successful) or
reach end of list (unsuccessful).
Sequential Search
Example for
Successful search.
Sequential Search
Example for
Unsuccessful search.
BINARY SEARCH.
✘ Sequential search algorithm is very slow. If an array of
1000 elements, exists, 1000 comparisons are made in
worst case.
✘ If the array is not sorted, the sequential search is the only
solution.
✘ However, if the array is sorted, we can use a more efficient
algorithm called binary search.
✘ Generally speaking, Binary search used whenever the list
starts to become large.
BINARY SEARCH.
✘ Begins by testing the data in the element at the middle of the array to
determine if the target is in the first or the second half of the list.
✘ If target in first half, there is NO need to check the second half.
✘ If target in second half, NO need to test the first half.
✘ In other words, half the list is eliminated from further consideration with
just one comparison.
✘ This process repeated, eliminating half of the remaining list with each
test, until target if found or does not exist in the list.
✘ To find the middle of the list, three variables needed: one to identify the
beginning of the list, one to identify the middle of the list, and one to
identify the end of the list.
Binary Search
Example for
Successful search.
Binary Search
Example for
Unsuccessful search.
✘ End
Special forms of square
matrices- Sparse, Polynomial
2-Dimensional Arrays
Matrices
• A m x n matrix is a table with m rows and n columns (m and n are the
dimensions of the matrix)
2
Matrices (Continued …)
• Representations (mapped as 1-D array)
3
Special forms of square matrices (m = n)
• Diagonal: M (i, j) = 0 for i ≠j
• Diagonal entries = m
4
Special forms of square matrices (m = n)
• Tridiagonal: M (i, j) = 0 for | i –j | > 1
✓ 3 diagonals: Main →i = j; Upper →i = j + 1; Lower →i=
j –1
✓ Number of elements on three diagonals: 3*m-2
✓ Mapping: row-major, column-major or diagonals (begin
with lowest)
5
Special forms of square matrices (m = n)
• Triangular matrices
✓ No. of elements in non-zero region: n (n + 1) / 2
✓ Upper triangular: M (i, j) = 0 for i>j
✓ Lower triangular: M (i, j) = 0 for i<j
7
Sparse Matrices
Sparse matrices
• Number of non-zero elements is very less compared to total number of
elements
• Represented as a 1-D array of triplets
✓ Element 1 onwards -Row, Column and Value –for all non-zero
elements
✓ Element 0 –number of rows, columns and non-zero elements
8
Polynomials
Polynomial
• An expression of the form
anxn+ a(n-1)x(n-1)+ … + a1x1+ a0
• One possible way of representation
✓ Store coefficients of the terms in an array element at position equal
to the exponent
✓ Disadvantage: Waste of space specially in case of sparse
polynomial
9
Polynomial(Continued …)
• Represented as a 1-D array of doublets
✓ Element 1 onwards -coefficient and exponent of all terms
✓ Element 0 –number of terms (either in coefficient or exponent
field)
10
Polynomial(Continued …)
• Represented as a linked list
✓ Store the coefficient and exponent (power) of each term in a
node of a singly linked list
11
int main()
{
//system("clear");
//clrscr();
//add polynomial as 1d array poly p1[10],p2[10],p3[20];
#include <stdio.h> printf("1st polynomial:\n");
typedef struct getpoly(p1);
printf("\n2nd polynomial:\n");
{ getpoly(p2);
int coeff, exp; printf("\n1st polynomial: ");
showpoly(p1);
} poly; printf("\n2nd polynomial: ");
showpoly(p2);
add(p1,p2,p3);
printf("\nSum : ");
showpoly(p3);
printf("\n");
return 0;
}
void getpoly(poly p[])
{
int n,i;
printf("Enter the number of terms: ");
scanf("%d",&n);
printf("Enter the terms (coefficient, exponent):\n");
p[0].coeff=n;
for(i=1;i<=n;i++)
scanf("%d %d",&p[i].coeff,&p[i].exp);
}
void showpoly(poly p[])
{
int i;
for(i=1;i<=p[0].coeff;i++)
printf("(%d,%d) ",p[i].coeff,p[i].exp);
}
void add(poly p1[],poly p2[],poly p3[]) else { while(i<=n1)
{ int sum=p1[i].coeff+p2[j].coeff; {
int i=1,j=1,n1=p1[0].coeff, if(sum!=0) n3++;
n2=p2[0].coeff,n3=0; { p3[n3].coeff=p1[i].coeff;
while(i<=n1 && j<=n2) n3++; p3[n3].exp=p1[i].exp;
{ p3[n3].coeff=sum; i++;
if(p1[i].exp>p2[j].exp) p3[n3].exp=p1[i].exp; }
{ } while(j<=n2)
n3++; i++; {
p3[n3].coeff=p1[i].coeff; j++; n3++;
} p3[n3].coeff=p2[j].coeff;
p3[n3].exp=p1[i].exp;
} p3[n3].exp=p2[j].exp;
i++;
j++;
} }
else if(p1[i].exp<p2[j].exp) p3[0].coeff=n3;
{ }
n3++;
p3[n3].coeff=p2[j].coeff;
p3[n3].exp=p2[j].exp;
j++;
}
END
GRAPHS.
Useful data structures.
WHAT WE KNOW ALREADY.
Need for ADTs and data structures:
Regular Arrays (with dynamic sizing)
Linked Lists
Stacks, Queues
Heaps
G=(V,E)
B
2 edges here
APPLICATIONS OF GRAPHS.
E
C
A
D
B B
The outdegree
The indegree is of a vertex in a
the number of digraph is the
arcs entering number of arcs
the vertex. leaving the
vertex.
When a vertex is
Delete vertex removes
deleted, all connecting
a vertex from the
edges are also
graph.
removed.
ADD EDGE.
If a vertex
If the graph is a
Add edge requires multiple To add an digraph, one of the
connects a edges, add an edge, two vertices must be
vertex to a edge must be vertices specified as the
destination called once for must be source and one as
vertex. each adjacent specified. the destination.
vertex.
Figure: Find vertex traverses the graph, looking for vertex C..
END.
GRAPH STORAGE
STRUCTURES.
Ref. Books: Corman & Forouzan
REPRESENTATIONS OF GRAPHS.
Choice between two standard ways to represent a graph G = (V, E):
As an adjacency matrix, or
As a collection of adjacency lists.
The two most common structures used to store these sets are arrays and
linked lists.
If two vertices are adjacent, that is, if there is an edge between them,
the intersect has a value of 1
1 1
1 1 1 1
1
ADJACENCY MATRIX FOR DIRECTED
GRAPH.
1
1 1
1 1
1 1
ADJACENCY MATRIX
An element of the adjacency matrix is either 0 or 1
Any matrix whose elements are either 0 or 1 is called bit matrix or Boolean matrix
For a given graph G =m (V, E), an adjacency matrix depends upon the ordering of the
elements of V
For different ordering of the elements of V we get different adjacency matrices.
V1 V4 V1 V2 V3 V4
V1 0 1 0 1
A = V2 1 0 0 0
V3 1 1 0 1
V4 0 1 0 0
V2 V3
ADJACENCY MATRIX
V1 V4 V1 V2 V3 V4
V1 0 1 0 1
A= V2 1 0 0 0
V3 1 1 0 1
V4 0 1 0 0
V2 V3
The vertex list is a singly linked list of the vertices in the list.
The pointer at the left of the list links the vertex entries.
The pointer at the right in the vertex is a head pointer to a linked list of
edges from the vertex.
ADJACENCY MATRIX FOR
UNDIRECTED GRAPH.
2. ADJACENCY LIST.
The adjacency-list representation of a graph G = (V,E) consists of an array
Adj of |V| lists, one for each vertex in V .
4
1
2
0 1 2 3 4
1 0 3
2 0 3 4
3 0 1 2 4
4 0 2 3
REPRESENTATIONS FOR UNDIRECTED GRAPH:
EXAMPLE 1.
1
2
3
4
5
REPRESENTATIONS FOR DIRECTED GRAPH:
EXAMPLE 2.
1
2
3
4
5
6
NETWORKS.
NETWORKS.
A network is a graph whose lines are weighted or called weighted graph.
Meaning of the weights depends on the application. For example, an airline might use
a graph to represent the routes between cities that it serves. Here,
Vertices represent cities, and
Vertices
Edge is a route between 2 cities. Edge
Edge’s weight could be:
Miles between the 2 cities
Price of the flight weight
STORING WEIGHTS IN GRAPH STRUCTURES .
▪ Since weight is an attribute of an
edge, it is stored in the structure that
contains the edge.
▪ In adjacency matrix, weight is stored as
the intersection value.
▪ In adjacency list, stored as the value in
the adjacency linked list.
INCIDENCE MATRIX OF A DIGRAPH.
Incidence matrix is a |E| x |V| matrix B = (bi j) such that,
E3 -1 0 1 0
It has one column for each vertex and one
E4 -1 0 0 1 row for each edge
E5 0 0 -1 1
DIRECTED ACYCLIC GRAPHS(DAG).
A directed graph with no directed cycles.
A A A
B C B C B C
D E D E D E
Directed Acyclic Graph Tree
Directed Graph
GRAPH TRAVERSAL
Two Commonly used Traversal Techniques are
Depth First Search (DFS)
Process all of a vertex’s descendants before moving to an adjacent vertex.
✓ B C ✓
M N O
✓D ✓ E F ✓ G ✓
R
Q P
H
✓
A B D H ECF G
✓ A
✓
✓B ✓ C E A B D C F E
✓ D F✓
BREADTH FIRST SEARCH (BFS)
Steps:
1. Begin by enqueuing vertex A in the
queue.
2. Then loop, dequeuing the queue and
processing the vertex from the front of
the queue. After processing the
vertex, place all of its adjacent
vertices into the queue. Thus, at
step 2, dequeue vertex X, process it,
and then place vertices G & H in the
queue. In step 3, process vertex G.
3. When queue is empty, traversal is
complete.
Breadth First Search (BFS)
✓ 1 ✓ A
✓ ✓
2 5 ✓ B ✓ C
✓ ✓
✓
3 4 ✓ D ✓ E F✓ G
6 ✓ 7 ✓
H✓
✓ 8 1 | 2 3 4 5 | 6 7 | 8 A| B C | D E F G | H
V4
V1
V2
V0 V6
V3 V0| V1 V2 | V4 V6 V3 | V5
V5
WRITE DFS & BFS OF FOLLOWING
GRAPHSA
B C
M N O
D E F G
R
Q P
H
A A
0 1
B C E B E
5 2
D F
4 3 C D
END.
THREADED TREES.
THREADED TREES.
• Binary tree traversal algorithms are written using either recursion or
programmer-written stacks. If the tree must be traversed frequently, using
stacks rather than recursion may be more efficient.
• A third alternative is a threaded tree. In a threaded tree, null pointers are
replaced with pointers to their successor nodes.
• To build a threaded tree ----> first build a standard binary search tree.
• Then traverse the tree, changing the null right pointers to point to their
successors.
• The traversal for a threaded tree is straightforward. Once you locate the
far-left node, loop happens, following the thread (the right pointer) to the
next node. No recursion or stack is needed. When you find a null thread
(right pointer), the traversal is complete.
Inorder traversal (LNR)
THREADED TREES.
6
7
Priority Queue
◼ Priority Queue
⚫ Queue: FIFO data structure
⚫ Priority Queue: Order of deletion is determined by the element’s
priority
Deleted either in increasing or decreasing priority
Efficiently implemented with heap data structure
– Heap is a complete binary tree; can be implemented using the array
representation
Other representations are leftist trees, fibonacci heaps, binomial heaps, skew
heaps and pairing heaps
9
– Implemented with linked data structures
AVL
TREES.
BALANCED TREES.
AVL TREES.
While the binary search tree is
simple and easy to understand, it
has one major problem.
Not balanced.
AVL TREES.
Also called AVL Search Trees.
In 1962, two Russian mathematicians,
G. M. Adelson-Velskii and E. M. Landis, created
the balanced binary tree structure named
after them
“the AVL tree”
AVL SEARCH TREES.
An AVL tree is a search tree in which the heights of
the subtrees differ by no more than 1.
{-1, 0, 1}
Search effort for this binary Search effort for this AVL tree
search tree is O(n) is O(log n)
Examples for AVL Trees.
An AVL tree is a height-balanced binary
search tree
AVL SEARCH TREES – Definition.
An AVL tree is a binary tree that either is empty or consists of two AVL
subtrees, TL, and TR,
whose heights differ by no more than 1.
HL is the height of the left subtree and HR is the height of the right subtree.
Because AVL trees are balanced by working with their height, they
are also known as height- balanced trees.
BALANCE FACTORS of AVL Trees.
Why BALANCING TREES?
Whenever we insert a node into a tree or delete a node from a tree, the
resulting tree may be unbalanced.
AVL trees are balanced by rotating nodes either to the left or to the right.
Consider the basic balancing algorithms for four cases of unbalancing:
UNBALANCED
Right of right
Left of left Right of left: Left of right:
A subtree of a tree
A subtree of a tree A subtree of a tree A subtree of a tree
that is right high has
that is left high has that is left high has that is right high has
also become right
also become left high. become right high. become left high.
high.
20 40
5 30
• Here 10 is printed and this node is pushed onto stack and then move left to 20.
This is done because we need to go right of 10 later.
Similarly 20, 5, 30 and 40 are moved to stack
• Once traversing the left side is over, pop the most pushed node and go to its right.
In the previous tree, after 5 is printed, recently pushed node 20 is popped and
move right to 30.
/*function for iterative preorder traversal*/
Void preorder(NODEPTR root)
{
NODEPTR cur;
NODEPTR stack[20];
int top=-1;
if(root==NULL)
{
printf(“tree is empty”);
return;
}
cur=root;
for(; ;)
{ while(cur!=NULL)
{
printf(“%d”, cur→info);
push(cur,&top,s) /*push the node to stack*/
cur=cur→llink;
}
if(!stack_empty(top)) /*more nodes existing*/
{
cur=pop(&top,s); /* pop most recent node*/
cur=cur→rlink; /*traverse right*/
}
else return;
}}
Ex: 10
20 40
5 30
10
20 40
5 30
Here 10, 20 , 5 is pushed to stack. Then pop 5, print it and move right.
Now pop 20, print it and move right and push 30 and move left.
Pop 30, print it and move right.
Pop 10, print it and move right and push 40 and so on
/*function for iterative inorder traversal*/
Void inorder(NODEPTR root)
{
NODEPTR cur;
NODEPTR stack[20];
int top=-1;
if(root==NULL)
{
printf(“tree is empty”);
return;
}
cur=root;
for(; ;)
{ while(cur!=NULL)
{
push(cur,&top,s) /*push the node to stack*/
cur=cur→llink;
}
if(!stack_empty(top)) /*more nodes existing*/
{
cur=pop(&top,s); /* pop most recent node*/
printf(“%d”, cur→info);
cur=cur→rlink; /*traverse right*/
}
else return;
}}
Ex: 10
20 40
5 30
Algorithm:
• Traverse left and push the nodes to stack with their flags set to 1, until
NULL is reached.
• Then flag of current node is set to -1 and its right subtree is traversed.
Flag is set to -1 to indicate that traversing right subtree of that node is
over.
• Hence is flag is -1, it means traversing right subtree of that node is
over and you can print the item. if flag is not –ve, traversing right is
not done, hence traverse right.
/*function for iterative postorder traversal*/
Void postorder(NODEPTR root)
{
struct stack
{
NODEPTR node;
int flag;
};
NODEPTR cur;
struct stack s[20];
int top=-1;
if(root==NULL)
{
printf(“tree is empty”);
return;
}
cur=root;
for(; ;)
{ while(cur!=NULL)
{ s[++top].node=cur; /*traverse left of tree and push the nodes to the stack and
s[top].flag=1; set flag to 1*/
cur=cur→llink;
}
while(s[top].flag<0)
{
cur=s[top--].node; /*if flag is –ve, right subtree is visited and hence node
printf(“%d”, cur→info); is poped and printed*/
if(stack_empty(top)) /*if stack is empty, traversal is complete*/
return;
}
cur= s[top].node; /*after left subtree is
cur=cur→rlink; traversed, move to right and
s[top].flag=-1; set its flag to -1 to indicate
right subtree is traversed*/
}
}
Ex: 10
20 40
5 30
s[top].flag =-1
Print 30
Stack is not empty, continue;
10. s[top].flag<0, 2nd While loop continues
cur=s[top].node; i.e cur=node 20;
Print 20
Stack is not empty, continue; 10 1