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

Algo Chap 3-5

Uploaded by

zerihun nana
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
22 views

Algo Chap 3-5

Uploaded by

zerihun nana
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
You are on page 1/ 153

Data structure and algorithm

Chapter Three

Data structure and Applications


Liked List

1
Introduction to Linked List
 Data structures can be divided into two types: static data structures
and dynamic data structures.
 Static data structures cannot change their form during program
execution.
array is an example of a static data structure.
 Arrays (and static data structures in general) have at least two
limitations:
their size has to be known at compile-time
the data in the array are stored in a continuous block of computer
memory
which means that inserting an item in the middle of the array
requires shifting other data in the array.
 These limitations can be overcome by using dynamic data
structures.
2  A dynamic data structure can change its form during program
Linked Lists
 linked list is a collection of objects called nodes, and a node
contains information and a link to the other node/nodes.
Advantages of Linked Lists
 Allocation of memory is more flexible in which memory is
allocated dynamically (allocation of memory during run time)
for each element as needed.
This implies that one need not know the size of the list in advance.
Memory is efficiently utilized.
 A linked list is made up of a chain of nodes. Each node
contains:
Data (information): the actual contents of the node
Link: a pointer to the next node

3
Limitation of Linked list
The memory is wasted as pointers require extra
memory for storage.
No element can be accessed randomly; it has to access
each node sequentially.
Reverse Traversing is difficult in linked list.
Applications of Linked Lists
Linked lists are used to implement stacks, queues,
graphs, etc.
Linked lists let you insert elements at the beginning and
end of the list.
In Linked Lists we don’t need to know the size in
4
advance.
Refreshment note on Structures in C++
 Structures are aggregate data types built using elements of primitive data
types.
 Structure are defined using the struct keyword:
E.g. struct Time{
int hour;
int minute;
int second;
};
 The struct keyword creates a new user defined data type that is used to
declare variables of an aggregate data type.
 Structure variables are declared like variables of other types.
 Syntax: struct <structure tag> <variable name>;
E.g. struct Time timeObject,
struct Time *timeptr;
5
Accessing Members of Structure Variables
The Dot operator (.): to access data members of
structure variables.
The Arrow operator (->): to access data members
of pointer variables pointing to the structure.
E.g. Print member hour of timeObject and timeptr.
cout<<timeObject.hour;
cout<<timeptr->hour;
TIP: timeptr->hour is the same as (*timeptr).hour.
The parentheses is required since (*) has lower
precedence than (.).
6
Operations on Linked List
 The primitive operations performed on the linked list

are as follows:

1. Creation

2. Insertion

3. Deletion

4. Searching

5. Traversing
7
Cont…
1. Creation operation is used to create a linked list.
 Once a linked list is created with one node, insertion operation

can be used to add more elements in a node.


2) Insertion operation is used to insert a new node at any
specified location in the linked list. A new node may be inserted.
(a) At the beginning of the linked list
(b) At the end of the linked list
(c) At any specified position in between in a linked list

8
Cont…
3. Deletion operation is used to delete an item (or node) from the
linked list. A node may be deleted from the:
(a) Beginning of a linked list
(b) End of a linked list
(c) Specified location of the linked list
4. Traversing is the process of going through all the nodes from
one end to another end of a linked list.
 In a singly linked list we can visit from left to right, forward
traversing, nodes only.
 But in doubly linked list forward and backward traversing is
possible.

9
Types of linked lists
Singly Linked Lists
Doubly Linked Lists
Circular Lists

10
Singly linked list
Singly linked list is a linked list, in which a node has
only one link which is a pointer to the next node.
Hence in a singly linked list, one can traverse through
the list in one direction only.
Creating Linked Lists in C++
 A linked list is a data structure that is built from
structures and pointers.
It forms a chain of "nodes" with pointers representing
the links of the chain and holding the entire thing
together

11
Cont………

next
 A singly linked list is a concrete
data structure consisting of a
sequence of nodes
 Each node stores
elem node
 element
 link to the next node

A B C D
12
Cont.…
• All the nodes in a singly linked list are arranged sequentially by
linking with a pointer.
• A singly linked list can grow or shrink, because it is a dynamic
data structure.

13
Cont..…
The operations we can perform on singly linked lists
are insertion, deletion and traversal.
A linked list can be represented by a diagram like the
following:

This linked list has four nodes in it, each with a link to
the next node in the series.
 The last node has a link to the special value NULL, to
show that it is the last link in the chain.
There is also another special pointer, called Start (also
called head), which points to the first link in the chain
14
so that we can keep track of it.
Defining the data structure for a linked list
 The key part of a linked list is a structure, which holds the data for each node (the
name, address, age or whatever for the items in the list), and, most importantly, a
pointer to the next node.
 Here we have given the structure of a typical node:
struct node {
char name[20];
int age;
float height;
node *nxt; // Pointer to next node
};
struct node *start_ptr = NULL;
 node *nxt; - gives a pointer to the next node in the list.
 We have also declared a pointer called start_ptr that will permanently point to
the start of the list.
 To start with, there are no nodes in the list, which is why start_ptr is set to
NULL.
15
Cont..

Some of the basic operations on a linked list are:-


Adding a node to a list
Deleting a node from a list
Searching a specific element from the list

16
Singly Linked List
Adding a node to the list
 All the nodes in a singly linked list are arranged sequentially by
linking with a pointer.
 A singly linked list can grow or shrink, because it is a dynamic
data structure.

17
Singly Linked List …
 Algorithm for Inserting a Node

 Insertion of New Node Suppose START is the first position in linked


list.
 Let DATA be the element to be inserted in the new node.
 POS is the position where the new node is to be inserted.
 TEMP is a temporary pointer to hold the node address.

18
Singly Linked List …

19
Singly Linked List …
 Insert a node at the end

Input DATA to be inserted


2. Create a NewNode
3. NewNode → DATA = DATA
4. NewNode → Next = NULL
5. If (SATRT equal to NULL)
(a) START = NewNode
6. Else
(a) TEMP = START
(b) While (TEMP → Next not equal to NULL)
(i) TEMP = TEMP → Next
20 7. TEMP → Next = NewNode
Cont..
 The first problem that we face is how to add a node to the list. For
simplicity's sake, we will assume that it has to be added to the end of
the list, although it could be added anywhere in the list (a problem we
will deal with later on).
 Firstly, we declare the space for a pointer item and assign a temporary
pointer to it. This is done using the new statement as follows:

 temp = new node;


 We can refer to the new node as *temp, i.e. "the node that temp
points to". When the fields of this structure are referred to, brackets
can be put round the *temp part, as otherwise the compiler will think
we are trying to refer to the fields of the pointer. Alternatively, we can
use the arrow pointer notation.
21
Cont…
 That's what we shall do here.
 Having declared the node, we ask the user to fill in the details of the
person, i.e. the name, age, address or whatever:

 cout<< "Please enter the name of the person: ";cin>> temp-


>name;cout<< "Please enter the age of the person : ";cin>> temp-
>age;cout<< "Please enter the height of the person : ";cin>> temp-
>height;temp->nxt = NULL;
 The last line sets the pointer from this node to the next to NULL,
indicating that this node, when it is inserted in the list, will be the last
node. Having set up the information, we have to decide what to do with
the pointers. Of course, if the list is empty to start with, there's no
problem - just set the Start pointer to point to this node (i.e. set it to the
same value as temp):
 if (start_ptr = = NULL)
22  start_ptr = temp;
Cont..
It is harder if there are already nodes in the list. In this
case, the secret is to declare a second pointer, temp2, to
step through the list until it finds the last node.

 temp2 = start_ptr; // We know this is not NULL -


list not empty!while (temp2->nxt != NULL) { temp2
= temp2->nxt; // Move to next link in chain } The
loop will terminate when temp2 points to the last node in
the chain, and it knows when this happened because the
nxt pointer in that node will point to NULL. When it has
found it, it sets the pointer from that last node to point to
the node we have just declared:
23
Cont.…
temp2->nxt = temp;

The link temp2->nxt in this diagram is the link joining


the last two nodes. The full code for adding a node at
the end of the list is shown below, in its own little
function:

24
Cont…
voidadd_node_at_end (){ node *temp, *temp2; //
Temporary pointers // Reserve space for new node
and fill it with datatemp = new node;cout<< "Please
enter the name of the person: ";cin>> temp-
>name;cout<< "Please enter the age of the person :
";cin>> temp->age;cout<< "Please enter the height of
the person : ";cin>> temp->height;temp->nxt =
NULL; // Set up link to this nodeif (start_ptr ==
NULL)start_ptr = temp;else{ temp2 =
start_ptr; // We know this is not NULL - list not
empty!while (temp2->nxt != NULL){ temp2 = temp2-
>nxt; // Move to next link in chain }
temp2->nxt = temp; } }
25
Cont…
temp = start_ptr;
do{
if (temp == NULL)
cout<< "End of list" <<endl;else{ // Display details for what temp points to
cout<< "Name : " << temp->name <<endl;
cout<< "Age : " << temp->age <<endl;
cout<< "Height : " << temp->height <<endl;cout<<endl; // Blank
line // Move to next node
(if present)temp = temp->nxt; } }
while (temp != NULL);

26
Deleting a node from the list
When it comes to deleting nodes, we have three choices:
Delete a node from the start of the list, delete one from the
end of the list, or delete one from somewhere in the middle.
Here is the function that deletes a node from the start:
void delete_start_node()
{
node *temp;
temp = start_ptr;
start_ptr = start_ptr->nxt;
void delete_end_node() delete temp; }
{ node *temp1, *temp2;
if (start_ptr == NULL)
cout << "The list is empty!" << endl;
else {
temp1 = start_ptr;
while (temp1->nxt != NULL) {
temp2 = temp1;
temp1 = temp1->nxt; }
delete temp1;
temp2->nxt = NULL; }

27
Singly Linked List …

28
Doubly Linked List
In a doubly linked list, each node contains two links
the first link points to the previous node and the next
link points to the next node in the sequence.
Items can be navigated forward and backward way.

29
Doubly Linked List …

 LPoint will point to the node in the left side (or previous node) that is LPoint

will hold the address of the previous node. RPoint will point to the node in the
right side (or next node) that is RPoint will hold the address of the next node.
DATA will store the information of the node.

30
Cont.…..

 A doubly linked list provides a natural


prev next
implementation of the List ADT
 Nodes implement Position and store:
 element
 link to the previous node
 link to the next node elem node
 Special trailer and header nodes
header
nodes/positions trailer

31
elements
Creating Doubly Linked Lists
The nodes for a doubly linked list would be defined as follows:
struct node{
char name[20];
node *nxt; // Pointer to next
node *prv; // Pointer to previous node
};
node *current;
current = new node;
current->name = "Fred";
current->nxt = NULL;
current->prv = NULL;
We have also included some code to declare the first node and set its pointers
to NULL. It gives the following situation:

32
Adding a Node to a Doubly Linked List

void add_node_at_start (string new_name)


{ // Declare a temporary pointer and move it to the start
node *temp = current;
while (temp->prv != NULL)
temp = temp->prv; // Declare a new node and link it in
node *temp2;
temp2 = new node;
temp2->name = new_name; // Store the new name in the node
temp2->prv = NULL; // This is the new start of the list
temp2->nxt = temp; // Links to current list
temp->prv = temp2; }

33
Cont..

void add_node_at_end ()
{// Declare a temporary pointer and move it to the end
node *temp = current;
while (temp->nxt != NULL)
temp = temp->nxt; // Declare a new node and link it in
node *temp2;
temp2 = new node;
temp2->name = new_name; // Store the new name in the node
temp2->nxt = NULL; // This is the new start of the list
temp2->prv = temp; // Links to current list
temp->nxt = temp2; }

34
Circular Linked List
 In the circular linked list the last node of the list
contains the address of the first node and forms a
circular chain.
Last item contains link of the first element as next and
first element has link to last element as prev.

35
Stack
 A simple data structure, in which insertion and deletion occur at the same end, is
termed (called) a stack. It is a LIFO (Last In First Out) structure.
It means: the last element inserted is the first one to be removed
 Anything added to the stack goes on the “top” of the stack
 Anything removed from the stack is taken from the “top” of the stack

 A stack is an abstract data type ADT, commonly used in most programming


languages. It is named
stack as it behaves like a real-world stack, for example − deck of cards or pile of
plates etc.
 A real-world stack allows operations at one end only. For example, we can place
or remove a card or plate from top of the stack only. Likewise, Stack ADT allows
all data operations at one end only.
At any given time, We can only access the top element of a stack.
 A stack is a limited access data structure - elements can be added and removed
from the stack only at the top
 A stack is a recursive data structure. Here is a structural definition of a Stack:
 a stack is either empty or it consists of a top and the rest which is a stack;
36
Static and Dynamic Stacks
Static Stacks
Fixed size
Can be implemented with an array.

Dynamic Stacks
Grow in size as needed
Can be implemented with a linked list

37
Cont..
 The operations of insertion and deletion are called PUSH and POP
respectively
 Push - push (put) item onto stack
 Pop - pop (get) item from stack

Applications
 The simplest application of a stack is to reverse a word. You push a given
word to stack - letter by letter - and then pop letters from the stack.
 Another application is an "undo" mechanism in text editors; this operation
is accomplished by keeping all text changes in a stack.
 Real life
 Pile of books
 Plate trays
 More applications related to computer science
 Program execution stack (read more from your text)
 Evaluating expressions

38
The Push Operation
Suppose we have an empty integer stack that is capable
of holding a maximum of three values. With that stack
we execute the following push operations.
The state of the stack after each of the push operations :

push(5);
push(10);
push(15);

39
The Pop Operation

Now, suppose we execute three consecutive pop


operations on the same stack:

40
Cont.….
Initial stack push(8) pop

8
TOS=>
4 4 4
TOS=> 1 1
TOS=>
1
3 3 3
6 6 6

41
Cont. ….

Implementation:
Stacks can be implemented both as an array
(contiguous list) and as a linked list. We want a set of
operations that will work with either type of
implementation: i.e. the method of implementation is
hidden and can be changed without affecting the
programs that use them.

42
Cont..
The Basic Operations:
Push() {
if there is room {
put an item on the top of the stack
else
give an error message
}}
Pop() { if stack not empty {
return the value of the top item
remove the top item from the stack }
else {
give an error message
}}
CreateStack() {
remove existing items from the stack
initialise the stack to empty
}
43
Array Implementation of Stacks: The
PUSH operation
Here, as you might have noticed, addition of an element is
known as the PUSH operation. So, if an array is given to you,
which is supposed to act as a STACK, you know that it has to
be a STATIC Stack; meaning, data will overflow if you cross
the upper limit of the array. So, keep this in mind.
Algorithm:
Step-1: Increment the Stack TOP by 1. Check whether it is
always less than the Upper Limit of the stack. If it is less than
the Upper Limit go to step-2 else report -"Stack Overflow"
Step-2: Put the new element at the position pointed by the
TOP

44
Cont..
Push operation involves series of steps −
Step 1 − Check if stack is full.
Step 2 − If stack is full, produce error and exit.
Step 3 − If stack is not full, increment top to point
next empty space.
Step 4 − Add data element to the stack location, where
top is pointing.
Step 5 − return success.

45
Implementation:
 static int stack[UPPERLIMIT];
int top= -1; /*stack is empty*/
..
..
main()
{
..
..
push(item);
..
..
}
 push(int item)
{
top = top + 1;
if(top < UPPERLIMIT)
 stack[top] = item; /*step-1 & 2*/
else
cout<<"Stack Overflow";
}
 Note:- In array implementation,we have taken TOP = -1 to signify the empty stack, as this
46 simplifies the implementation.
Array Implementation of Stacks: the POP operation

 POP is the synonym for delete when it comes to Stack. So, if


you're taking an array as the stack, remember that you'll return
an error message, "Stack underflow", if an attempt is made to
Pop an item from an empty Stack. OK.
Algorithm
 Step-1: If the Stack is empty then give the alert "Stack
underflow" and quit; or else go to step-2
Step-2: a) Hold the value for the element pointed by the TOP
b) Put a NULL value instead
c) Decrement the TOP by 1

47
Cont. …..
Implementation:
static int stack[UPPPERLIMIT];
int top=-1;
..
..
main()
{
..
..
poped_val = pop();
..
..
}
int pop()
{
int del_val = 0;
if(top == -1)
cout<<"Stack underflow"; /*step-1*/
else
{
del_val = stack[top]; /*step-2*/
stack[top] = NULL;
top = top -1;
}
return(del_val);
}
48 Note: - Step-2:(b) signifies that the respective element has been deleted.
Linked List Implementation of Stacks: the
PUSH operation
It’s very similar to the insertion operation in a dynamic
singly linked list. The only difference is that here you'll
add the new element only at the end of the list, which
means addition can happen only from the TOP.
 In Step [1] we create the new element to be pushed to the
Stack.
In Step [2] the TOP most element is made to point to our
newly created element.
In Step [3] the TOP is moved and made to point to the last
element in the stack, which is our newly added element.

49
Algorithm
Step-1: If the Stack is empty go to step-2 or else go to
step-3
Step-2: Create the new element and make your "stack"
and "top" pointers point to it and quit.
Step-3: Create the new element and make the last (top
most) element of the stack to point to it
Step-4: Make that new element your TOP most element
by making the "top" pointer point to it.

50
Cont.…
Implementation:
struct node{
int item;
struct node *next;
}
struct node *stack = NULL; /*stack is initially empty*/
struct node *top = stack;
main()
{
..
push(item);
..}
push(int item){
if(stack == NULL) {/*step-1*/
newnode = new node /*step-2*/
newnode -> item = item;
newnode -> next = NULL;
stack = newnode;
top = stack;}
else{
newnode = new node; /*step-3*/
newnode -> item = item;
newnode -> next = NULL;
top ->next = newnode;
top = newnode; /*step-4*/
}}
51
Linked List Implementation of Stacks: the POP
Operation
This is again very similar to the deletion operation in any Linked
List, but you can only delete from the end of the list and only one at
a time; and that makes it a stack. Here, we'll have a list pointer,
"target", which will be pointing to the last but one element in the
List (stack). Every time we POP, the TOP most element will be
deleted and "target" will be made as the TOP most element.
In step[1] we got the "target" pointing to the last
but one node.
In step[2] we freed the TOP most element.
In step[3] we made the "target" node as our
TOP most element.
Supposing you have only one element left in the
Stack, then we won't make use of "target" rather
we'll take help of our "bottom" pointer. See
how...

52
Cont.…
Algorithm:
Step-1: If the Stack is empty then give an alert
message "Stack Underflow" and quit; or else proceed
Step-2: If there is only one element left go to step-3 or
else step-4
Step-3: Free that element and make the "stack", "top"
and "bottom" pointers point to NULL and quit
Step-4: Make "target" point to just one element before
the TOP; free the TOP most element; make "target" as
your TOP most element

53
Implementation:
struct node{
int nodeval;
struct node *next;};
struct node *stack = NULL; /*stack is initially empty*/
struct node *top = stack;
main(){
int newvalue, delval;
..
push(newvalue);
..
delval = pop(); } /*POP returns the deleted value from the stack*/
 int pop( ){
int pop_val = 0;
struct node *target = stack;
if(stack == NULL) /*step-1*/
cout<<"Stack Underflow";
else{
if(top == bottom) { /*step-2*/
pop_val = top -> nodeval; /*step-3*/
delete top;
stack = NULL;
top = bottom = stack;}
else{ /*step-4*/
while(target->next != top) target = target ->next;
pop_val = top->nodeval;
delete top;
top = target;
target ->next = NULL; }}return(pop_val);}
54
Applications of Stacks
Evaluation of Algebraic Expressions
Mathematical Calculations
What is 3 + 2 * 4? 2 * 4 + 3? 3 * 2 + 4?
Simple calculator 20 for 3+2*4
Scientific calculator 11 for 3+2*4
 The precedence of operators affects the order of
operations. A mathematical expression cannot
simply be evaluated left to right.
 A challenge when evaluating a program.
Lexical analysis is the process of interpreting a program.
Note: Computers solve arithmetic expressions by
restructuring them so the order of each calculation is
embedded in the expression. Once converted an
55 expression can then be solved in one pass.
Types of Expression
1.Infix the normal or human way of expressing mathematical
expressions .Example 4+5*5
2. Prefix When the operators are written before their operands, it is called
the prefix form.
Example +4*55
3. Postfix When the operators come after their operands, it is called postfix
form (suffix form or reverse polish notation)
 Postfix expression does not require any precedence rules.
Example 455*+
3 2 * 1 + is postfix of 3 * 2 + 1
Note The two methods (prefix and postfix) called Polish Notation (because
this method was discovered by the Polish mathematician Jan Lukasiewicz).

56
Simple Example
Infix Expression: 3+2*4
PostFix Expression:
Operator Stack:

57
Simple Example
Infix Expression: +2*4
PostFix Expression: 3
Operator Stack:

58
Simple Example
Infix Expression: 2*4
PostFix Expression: 3
Operator Stack: +

59
Simple Example
Infix Expression: *4
PostFix Expression: 32
Operator Stack: +

60
Simple Example
Infix Expression: 4
PostFix Expression: 32
Operator Stack: +*

61
Simple Example
Infix Expression:
PostFix Expression: 324
Operator Stack: +*

62
Simple Example
Infix Expression:
PostFix Expression: 324*
Operator Stack: +

63
Simple Example
Infix Expression:
PostFix Expression: 324*+
Operator Stack:

64
Conti..

Consider the postfix expression :


6523+8*+3+*
Algorithm
initialise stack to empty;
while (not end of postfix expression) {
get next postfix item;
if(item is value)
push it onto the stack;
else if(item is binary operator) {
pop the stack to x;
pop the stack to y;
perform y operator x;
push the results onto the stack;
} else if (item is unary operator) {
pop the stack to x;
perform operator(x);
push the results onto the stack }}

65
Cont.….…
The single value on the stack is the desired result.
Binary operators: +, -, *, /, etc.,
Unary operators: unary minus, square root, sin, cos, exp, etc.,
So for 6 5 2 3 + 8 * + 3 + *

TOS=> 3
2
5
6
The remaining items are now: + 8 * + 3 + *
So next a '+' is read (a binary operator), so 3 and 2 are popped from the stack and their sum '5' is pushed onto the stack:

TOS => 8
TOS=> 5 Next 8 is pushed and next item is TOS=> 40
5
5 the operator * 5
5
(8 ,5 poped,40 pushed) 6
6 6

66
Cont.….
Next + followed by 3

TOS=> 45 3
TOS=>
6 45
6 40, 5 popped, 45 pushed, 3 pushed

Next is operator +, so 3 and 45 are popped and 45+3=48 is pushed

48

Next is operator *, so 48 and 6 are popped, and 6*48=288 is 6pushed

288

Now there are no more items and there is a single value on the stack, representing the final answer 288.

67
Exercise
evaluate the following postfix expressions and write
out a corresponding infix expression:
2324*+* 1234^*+
377*+

68
Queue
 a data structure that has access to its data at the front and
rear.
 A queue is a first in, first out (FIFO) data structure.
 has two basic operations:
enqueue - inserting data at the rear of the queue
dequeue – removing data
dequeu enqueuat the front of the queue
e e

Front Rear

0 1 2 3 4 5 6 7
myQueue:
17 23 97 44

front = 0 rear = 3
 To insert: put new element in location 4, and set rear to 4
 To delete: take element from location 0, and set front to 1

69
Cont.…
example

front = 0 rear = 3

Initial queue: 17 23 97 44

After insertion: 17 23 97 44 333

After deletion: 23 97 44 333

front = 1 rear = 4

 Notice how the array contents “crawl” to the right as elements are inserted and
deleted
 This will be a problem after a while!

70
Cont.…
Example 2
Operation Content of queue

Enqueue(B) B

Enqueue(C) B, C

Dequeue() C

Enqueue(G) C, G

Enqueue (F) C, G, F

Dequeue() G, F

Enqueue(A) G, F, A

Dequeue() F, A

71
Simple array implementation of Enqueue and Dequeue opertion
const int MAX_SIZE=100;
int FRONT =-1, REAR =-1;
int QUEUESIZE = 0;
void enqueue(int x){
if(Rear<MAX_SIZE-1) {
REAR++;
Num[REAR]=x;
QUEUESIZE++;
if(FRONT = = -1)
FRONT++;}
else
cout<<"Queue Overflow";}
int dequeue(){
int x;
if(QUEUESIZE>0) {
x=Num[FRONT];
FRONT++;
QUEUESIZE--;}
else
cout<<"Queue Underflow";
return(x);}
72
Priority Queue
Priority Queue
- is a queue where each data has an associated
key that is provided at the time of insertion.
- Dequeue operation deletes data having highest
priority in the list
- One of the previously used dequeue or enqueue
operations has to be modified
 Example: Consider the following queue of
persons where females have higher priority
than males (gender is the key to give priority).

73
Cont..
 Dequeue()- deletes Aster

Dequeue()- deletes Meron

 Now the queue has data having equal priority and


dequeue operation deletes the front element like in the
case of ordinary queues.
Dequeue()- deletes Abebe

74
Application of Queues
A.Print server- maintains a queue of print jobs
Print(){
EnqueuePrintQueue(Document)
}
EndOfPrint(){
DequeuePrintQueue()
}
B.Disk Driver- maintains a queue of disk input/output requests
C.Task scheduler in multiprocessing system- maintains priority queues of
processes .
D.Telephone calls in a busy environment –maintains a queue of telephone calls
E. Simulation of waiting line- maintains a queue of persons

75
//Trees
 A tree is a set of nodes and edges that connect pairs of
nodes. It is an abstract model of a hierarchical structure.
Rooted tree has the following structure:
 One node distinguished as root.
 Every node C except the root is connected from exactly
other node P. P is C's parent, and C is one of C's children.
 There is a unique path from the root to the each node.
 The number of edges in a path is the length of the path.
 A tree consists of finite set of elements, called nodes, and
a finite set of directed lines called branches, that connect
the nodes.
 The number of branches associated with a node is the
degree of the node.
76
Cont.….
 A leaf is any node with an outdegree of zero, that is, a node
with no successors.
 A node that is not a root or a leaf is known as an internal node.
 A node is a parent if it has successor nodes; that is, if it has
outdegree greater than zero.
 A node with a predecessor is called a child.
 Two or more nodes with the same parents are called siblings.
 An ancestor is any node in the path from the root to the node.
 A descendant is any node in the path below the parent node;
that is, all nodes in the paths from a given node to a leaf are
descendants of that node.

77
Cont.…
 A path is a sequence of nodes in which each node is
adjacent to the next node.
 The level of a node is its distance from the root. The root is
at level 0, its children are at level 1, etc. …
 The height of the tree is the level of the leaf in the longest
path from the root plus 1. By definition the height of any
empty tree is -1.
 A subtree is any connected structure below the root. The
first node in the subtree is known is the root of the subtree.
 The sum of the indegree and outdegree branches is the
degree of the node.
 If the tree is not empty, the first node is called the root.
 Children of the same parent are siblings.
78
Cont..
Consider the following tree

79
Cont..
 Root:a node with out a parent. A
 Internal node: a node with at least one child.A, B, F, I, J
 External (leaf) node: a node without a child. C, D, E, H, K, L,M, G
 Ancestors of a node:parent, grandparent, grand-grandparent, etc of a node.
-Ancestors of K A, F, I
 Descendants of a node: children, grandchildren, grand-grandchildren etc of a node.
 -Descendants of F H, I, J, K, L, M
 Depth of a node: number of ancestors or length of the path from the root to the node.
-Depth of H 2
 Height of a tree: depth of the deepest node .  3
 Subtree: a tree consisting of a node and its descendants.
 Children of the same parent are siblings.
 The node with degree 0 is a leaf or terminal
node.
 The degree of a node is the number of subtrees
of the node .The degree of A is 4; the degree of C is 0.
 The node with degree 0 is a leaf or terminal
node.
80
Binary Tree
a tree in which each node has at most two children called left child and
right child. Any tree can be transformed into binary tree. Binary tree has
the following property
 All items in the left subtree are less than the root.
 All items in the right subtree are greater or equal to the root.
 Each subtree is itself a binary search tree.

Full binary tree


 a binary tree where each node has either 0 or 2 children.
81
Balanced binary tree:
a binary tree where each node except the leaf nodes has left
and right children and all the leaves are at the same level.

Complete binary tree: a binary tree in which the length


from the root to any leaf node is either h or h-1 where h is
the height of the tree. The deepest level should also be filled
from left to right.

82
83
Binary search tree (ordered binary tree):
a binary tree that may be empty, but if it is not empty it
satisfies the following.
 Every node has a key and no two elements have the same
key.
 The keys in the right subtree are larger than the keys in the
root.
 The keys in the left subtree are smaller than the keys in the
root.
 The left and the right subtrees are also binary search trees.

84
Cont.……

85
Data Structure of a Binary Tree

struct DataModel{
Declaration of data fields
DataModel * Left, *Right;};
DataModel *RootDataModelPtr=NULL;
Insertion
When a node is inserted the definition of binary search tree should be preserved. Suppose
there is a binary search tree whose root node is pointed by RootNodePtr and we want to
insert a node (that stores 17) pointed by InsNodePtr.

Case 1: There is no data in the tree (i.e. RootNodePtr is NULL)


The node pointed by InsNodePtr should be made the root node.

InsNodePtr RootNodePtr RootNodePt


 r

17 17

86
Cont. ….
Case 2: There is data
-Search the appropriate position.
-Insert the node in that position.

87
Traversing
Binary search tree can be traversed in three ways.
A.Pre order traversal- traversing binary tree in the order of parent, left and right.
B.Inorder traversal- traversing binary tree in the order of left, parent and right.
C.Postorder traversal- traversing binary tree in the order of left, right and parent.
Example

 Preorder traversal - 10, 6, 4, 8, 7, 15, 14, 12, 11, 13, 18, 16, 17, 19
 Inorder traversal - 4, 6, 7, 8, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19
==> Used to display nodes in ascending order.
 Postorder traversal- -4, 7, 8, 6, 11, 13, 12, 14, 17, 16, 19, 18, 15, 10
88
Application of binary tree traversal
 Store values on leaf nodes and operators on internal nodes
 Preorder traversal- used to generate mathematical expression in prefix
notation.
 Inorder traversal- used to generate mathematical expression in infix
notation.
 Postorder traversal- used to generate mathematical expression in
postfix notation.

89
Cont..
Function call
Preorder(RootNodePtr);
Inorder(RootNodePtr);
Function call

Postorder(RootNodePtr);
Implementation:

void Preorder (Node *CurrNodePtr){


if(CurrNodePtr ! = NULL){
cout<< CurrNodePtr->Num; // or any operation on the node
Preorder(CurrNodePtr->Left);
Preorder(CurrNodePtr->Right);}}
void Inorder (Node *CurrNodePtr){
if(CurrNodePtr ! = NULL){
Inorder(CurrNodePtr->Left);
cout<< CurrNodePtr->Num; // or any operation on the node
Inorder(CurrNodePtr->Right);
}

90
Cont….
void Postorder (Node *CurrNodePtr){
if(CurrNodePtr ! = NULL){
Postorder(CurrNodePtr->Left);
Postorder(CurrNodePtr->Right);
cout<< CurrNodePtr->Num; // or any operation on the node
}}

91
Search
To search a node (whose Num value is Number) in a binary search tree (whose root
node is pointed by RootNodePtr), one of the three traversal methods can be used.
Function call:
ElementExists = SearchBST (RootNodePtr, Number);
// ElementExists is a Boolean variable defined as: bool ElementExists = false;
Implementation:
bool SearchBST (Node *RNP, int x){
if(RNP = = NULL)
return(false);
else if(RNP->Num = = x)
return(true);
else if(RNP->Num > x)
return(SearchBST(RNP->Left, x));
else
return(SearchBST(RNP->Right, x));}
92
Cont.…..

When we search an element in a binary search tree, sometimes it may be necessary for the Search
BST function to return a pointer that points to the node containing the element searched.
Accordingly, the function has to be modified as follows.
Function call:
SearchedNodePtr = SearchBST (RootNodePtr, Number);
// SearchedNodePtr is a pointer variable defined as: Node *SearchedNodePtr=NULL;
Implementation:

Node *SearchBST (Node *RNP, int x){


if((RNP = = NULL) || (RNP->Num = = x))
return(RNP);
else if(RNP->Num > x)
return(SearchBST(RNP->Left, x));
else
return(SearchBST (RNP->Right, x));}

93
Deletion
To delete a node (whose Num value is N) from binary search tree (whose root node
is pointed by RootNodePtr), four cases should be considered. When a node is
deleted the definition of binary search tree should be preserved.
Consider the following binary search tree.

94
Cont.…..
Case 1: Deleting a leaf node (a node having no child), e.g. 7

95
Cont..

Case 2: Deleting a node having only one child, e.g. 2


Approach 1: Deletion by merging – one of the following is done
 If the deleted node is the left child of its parent and the deleted node has
only the left child, the left child of the deleted node is made the left child
of the parent of the deleted node.
 If the deleted node is the left child of its parent and the deleted node has
only the right child, the right child of the deleted node is made the left
child of the parent of the deleted node.
 If the deleted node is the right child of its parent and the node to be
deleted has only the left child, the left child of the deleted node is made
the right child of the parent of the deleted node.
 If the deleted node is the right child of its parent and the deleted node
has only the right child, the right child of the deleted node is made the
right child of the parent of the deleted node.
96
Cont.…

97
Cont..
Approach 2: Deletion by copying- the following is done
 Copy the node containing the largest element in the left (or the smallest element in the right) to
the node containing the element to be deleted
 Delete the copied node

98
Cont.….
Case 3: Deleting a node having two children, e.g. 6
Approach 1: Deletion by merging – one of the following is done
If the deleted node is the left child of its parent, one of the following is done
 The left child of the deleted node is made the left child of the parent of the deleted node,
and
 The right child of the deleted node is made the right child of the node containing largest
element in the left of the deleted node
OR
 The right child of the deleted node is made the left child of the parent of the deleted node, and
 The left child of the deleted node is made the left child of the node containing smallest
element in the right of the deleted node
OR
 The right child of the deleted node is made the right child of the parent of the deleted node, and
 The left child of the deleted node is made the left child of the node containing smallest
element in the right of the deleted node

99
Cont.….

100
Cont..

101
Cont.…..
Approach 2: Deletion by copying- the following is done
 Copy the node containing the largest element in the left (or the smallest element in the right) to
the node containing the element to be deleted
 Delete the copied node

102
Cont.….

Cont.….

103

CaseIf the tree
4: Deleting the roothas
node, only
10 one node the root node pointer is made to point to nothing
(NULL)
 If the root node has left child

the root node pointer is made to point to the left child


the right child of the root node is made the right child of the node containing
the largest element
 If root node has right child

the root node pointer is made to point to the right child


the left child of the root node is made the left child of the node containing the
smallest element in the right of the root node

104
Cont.….

105
//Graphs
A graph is a pictorial representation of a set of objects where
some pairs of objects are connected
by links. The interconnected objects are represented by points
termed as vertices, and the links that connect the vertices are
called edges.
Formally, a graph is a pair of sets V, E, where V is the set of
vertices and E is the set of edges,
connecting the pairs of vertices. Take a look at the following
graph a b
In the above graph,
c d
V = {a, b, c, d, }
E = {ab, ac, bd, cd, }
106
Cont. ….
 Each edge connects two different vertices.
 Edges are also called arcs and lines.
 Directed edge has an orientation (u,v).
u v
 Undirected edge has no orientation (u,v).
u v
 Undirected graph => no oriented edge.
 Directed graph => every edge has an orientation.

107
Undirected Graph
2
3
8
1 10

4
5
9
11

6
7

108
Directed Graph (Digraph)
2
3
8
1 10

4
5
9
11

6
7

109
Applications—Communication Network
2
3
8
1 10

4
5
9
11

6
7

Vertex = city, edge = communication link.

110
Street Map
2
3
8
1 10

4
5
9
11

6
7

Some streets are one way.


111
Driving Distance/Time Map
2
4 3
8 8
1 6 10
2 4 5
4 4 3
5
9
11
5 6

6 7
7

Vertex = city, edge weight = driving distance/time.

112
Cont.…
 Number of edges in an undirected graph is <= n(n-1)/2.
 Number of edges in a directed graph is <= n(n-1).

Vertex Degree 2
3
8
1 10

4
5
9
11

6
7

Number of edges incident to vertex.


113
degree(2) = 2, degree(5) = 3, degree(3) = 1
In-Degree Of A Vertex
2
3
8
1 10

4
5
9
11

6
7

in-degree is number of incoming edges


indegree(2) = 1, indegree(8) = 0
114
Out-Degree Of A Vertex
2
3
8
1 10

4
5
9
11

6
7

out-degree is number of outbound edges


115 outdegree(2) = 1, outdegree(8) = 2
Chapter Four.
Advanced Sorting and Searching Algorithms
Shell Sort
Shell sort is an improvement of insertion sort. The shell
sort, also known as the diminishing increment sort. It is
developed by Donald Shell in 1959. Insertion sort works
best when the array elements are sorted in a reasonable
order. Thus, shell sort first creates this reasonable order.
Algorithm:
Choose gap gk between elements to be partly ordered.
Generate a sequence (called increment sequence) gk, gk-1,
…., g2, g1 where for each sequence gi, A[j]<=A[j+gi] for
0<=j<=n-1-gi and k>=i>=1
116
 The shell sort, also known as the diminishing increment sort, was developed by
Donald L. Shell in 1959. The idea behind shell sort is that it is faster to sort an
Cont.…

array if parts of it are already sorted. The original array is first divided into a
number of smaller subarrays, these subarrays are sorted, and then they are
combined into the overall array and this is sorted. A general outline of such a
procedure is:
Divide data into h subarrays
for (i = 1; i < h; i++)
Sort subarray i
Sort array data
How should the original array be divided into subarrays? One approach would be
to divide the array into a number of subarrays consisting of contiguous elements
(i.e. elements that are next to each other). For example, the array [abcdef] could
be divided into the subarrays [abc] and [def]. However, shell sort uses a different
approach: the subarrays are constructed by taking elements that are regularly
spaced from each other. For example, a subarray may consist of every second
element in an array, or every third element, etc. For example, dividing the array
[abcdef] into two subarrays by taking every second element results in the
subarrays [ace] and [bdf].
117
Example: Sort the following list using shell sort algorithm.

5 8 2 4 1 3 9 7 6 0

Choose g3 =5 (n/2 where n is the number of elements =10)

Sort (5, 3) 3 8 2 4 1 5 9 7 6 0
Sort (8, 9) 3 8 2 4 1 5 9 7 6 0
Sort (2, 7) 3 8 2 4 1 5 9 7 6 0
Sort (4, 6) 3 8 2 4 1 5 9 7 6 0
Sort (1, 0) 3 8 2 4 0 5 9 7 6 1
 5- sorted list 3 8 2 4 0 5 9 7 6 1
Choose g2 =3
Sort (3, 4, 9, 1) 1 8 2 3 0 5 4 7 6 9
Sort (8, 0, 7) 1 0 2 3 7 5 4 8 6 9
Sort (2, 5, 6) 1 0 2 3 7 5 4 8 6 9
 3- sorted list 1 0 2 3 7 5 4 8 6 9

Choose g1 =1 (the same as insertion sort algorithm)


Sort (1, 0, 2, 3, 7, 5, 4, 8, 6, 9) 0 1 2 3 4 5 6 7 8 9
 1- sorted (shell sorted) list 0 1 2 3 4 5 6 7 8 9

118
Heap Sort
Heap is a binary tree that has two properties:
I. The value of each node is greater than or equal to the values stored in each of
its children.
II. The tree is perfectly balanced, and the leaves in the last level are all in the
leftmost positions.
 A property of the heap data structure is that the largest element is always at the
root of the tree.
 A common way of implementing a heap is to use an array. The heap sort works
by first rearranging the input array so that it is a heap, and then removing the
largest elements from the heap one by one. Pseudo code code for the heap sort
is given below.
HeapSort(data):
Transform data into a heap
for (i = n-1; i > 1; i--)
Swap the root with element in position i
Restore the heap property for the tree data[0] … data[i-1]
119
Example
a heap
a heap
53

44 25

15 21 13 18

3 12 5 7

120
Cont.….
an example of applying the heap sort algorithm. To begin
with, in Figure a, the array has been arranged as a heap.
The largest element, 10, is removed and swapped with
the last element. In Figure b, the last element of the array
is shaded and the corresponding tree node is surrounded
by a dotted line to indicate that it will not be considered
in the algorithm. Moving the 3 element to the root has
violated the first heap condition, so it is restored by
calling moveDown(), resulting in the tree in Figure c.
Next, the root node 9 is swapped with the last element 2,
and the heap conditions are restored again. This process
continues until only one element remains in the heap.
Then we know that the array has been sorted.
121
Cont.…

122
Sample Run
Start with unordered array of data
Array representation:
Binary tree representation:

21 15 25 3 5 12 7 19 45 2 9

21

15 25

3 5 12 7

19 45 2 9

123
Types of Heap sort
Min Heap. where the value of root node is less than or equal
to either of its children. For every node excluding the root,
value is at least that of its parent: A[parent[i]]  A[i]
Smallest element is stored at the root.
In any subtree, no values are smaller than the value
stored at subtree10root

19
14
27
26 31 42

3
44 35 3

124
Max Heap
where the value of root node is greater than or equal to either
of its children. For every node excluding the root,
value is at most that of its parent: A[parent[i]]  A[i]
Largest element is stored at the root.
In any subtree, no values are larger than the value
stored at subtree
44
root..

35
42
2
19 7
3 3
3 1
2
6
10
14

125
Quicksort
 Quicksort was developed by C. A. R. Hoare in 1961, and is probably the most famous
and widely used of sorting algorithms.
 it is more efficient to sort a number of smaller subarrays than to sort one big array.
 Quick sort is a highly efficient sorting algorithm and is based on partitioning of array
of data into smaller arrays.
 The quick sort partitions an array and then calls itself recursively twice to sort the
resulting two subarray. This algorithm is quite efficient for large sized
 In quicksort the original array is first divided into two subarrays, the first of which
contains only elements that are less than or equal to a chosen element, called the
bound or pivot. The second subarray contains elements that are greater than or
equal to the bound.
 If each of these subarrays is sorted separately they can be combined into a final sorted
array. To sort each of the subarrays, they are both subdivided again using two new
bounds, making a total of 4 subarrays.
 The partitioning is repeated again for each of these subarrays, and so on until the
subarrays consist of a single element each, and do not need to be sorted.

 Quicksort is inherently recursive in nature, since it consists of the same simple

126
operation (the partitioning) applied to successively smaller subarrays.
Cont.…
Quick sort is the fastest known algorithm. It uses divide and
conquer strategy and in the worst case its complexity is O
(n2). But its expected complexity is O(nlogn).
Algorithm:
Choose a pivot value (mostly the first element is taken as
the pivot value)
Position the pivot element and partition the list so that:
The left part has items less than or equal to the pivot value
The right part has items greater than or equal to the pivot
value
Recursively sort the left part
Recursively sort the right part
127
The following algorithm can be used to position a pivot value and create partition.

Left=0;
Right=n-1; // n is the total number of elements in the list
PivotPos=Left;
while(Left<Right){
if(PivotPos==Left){
if(Data[Left]>Data[Right]){
swap(data[Left], Data[Right]);
PivotPos=Right;
Left++;}
else
Right--;}
else{
if(Data[Left]>Data[Right]){
swap(data[Left], Data[Right]);
PivotPos=Left;
Right--; }
else
Left++;}}
128
Fig a

129
Cont.….
 QuickSort Pivot Algorithm
 Based on our understanding of partitioning in quicksort, we should
now try to write an algorithm
 for it here.
S tep 1 − Choose the highest index value has pivot
S tep 2 − Take two variables to point left and right of the list excluding
pivot
S tep 3 − left points to the low index
S tep 4 − right points to the high
S tep 5 − while value at left is less than pivot m ove right
S tep 6 − while value at right is greater than pivot m ove left
S tep 7 − if both step 5 and step 6 does not m atch swap left and right
S tep 8 − if left ≥ right, the point where they m et is new pivot
130
Merge sort
 Merge sort works by successively partitioning the array into two
subarrays, but it guarantees that the subarrays are of approximately
equal size. This is possible because in mergesort the array is
partitioned without regard to the values of their elements: it is
simply divided down the middle into two halves. Each of these
halves is recursively sorted using the same algorithm. After the two
subarrays have been sorted, they are merged back together again.
The recursion continues until the subarrays consist of a single
element, in which case they are already sorted.
Algorithm:
 Divide the array in to two halves.
 Recursively sort the first n/2 items.
 Recursively sort the last n/2 items.
 Merge sorted items (using an auxiliary array).

131
Cont.…

132
Chapter 5

Hash

133
Dictionary
Dictionary:
Dynamic-set data structure for storing items indexed using keys.
Supports operations Insert, Search, and Delete.
Applications:
 Symbol table of a compiler.
 Memory-management tables in operating systems.
 Large-scale distributed systems.

Hash Tables:
Effective way of implementing dictionaries.
Generalization of ordinary arrays.

134
Direct-address Tables
Direct-address Tables are ordinary arrays.
Facilitate direct addressing.
Element whose key is k is obtained by indexing into the kth
position of the array.
Applicable when we can afford to allocate an array with one
position for every possible key.
i.e. when the universe of keys U is small.
Dictionary operations can be implemented to take O(1) time.
Details in Sec. 11.1.

135
Hash Tables
Notation:
U – Universe of all possible keys.
K – Set of keys actually stored in the dictionary.
 |K| = n.
When U is very large,
Arrays are not practical.
|K| << |U|.
Use a table of size proportional to |K| – The hash tables.
However, we lose the direct-addressing ability.
Define functions that map keys to slots of the hash table.

136
Hashing
Hash function h: Mapping from U to the slots of a hash table
T[0..m–1].
h : U  {0,1,…, m–1}
With arrays, key k maps to slot A[k].
With hash tables, key k maps or “hashes” to slot T[h[k]].
h[k] is the hash value of key k.

137
Hashing
0
U
(universe of keys) h(k1)

h(k4)
K k1 k4
(actual k2 collisio h(k2)=h(k5)
keys) k5
k3 n
h(k3)

m–1

138
Issues with Hashing
Multiple keys can hash to the same slot – collisions are
possible.
Design hash functions such that collisions are minimized.
But avoiding collisions is impossible.
 Design collision-resolution techniques.

Search will cost Ө(n) time in the worst case.


However, all operations can be made to have an expected
complexity of Ө(1).

139
Methods of Resolution
Chaining: 0
k1 k4

Store all elements that hash to the same slot in


a linked list. k5 k2 k6

Store a pointer to the head of the linked list in k7


k8
k3

the hash table slot. m–1

Open Addressing:
All elements stored in hash table itself.
When collisions occur, use a systematic
(consistent) procedure to store elements in free
slots of the table.

140
Collision Resolution by Chaining
0
U
(universe of keys) h(k1)=h(k4)
X
k1
k4
K
(actual k2 k6 X
k5 h(k2)=h(k5)=h(k6)
keys)
k8 k7
k3
X h(k3)=h(k7)
h(k8)
m–1

141
Collision Resolution by Chaining
0
U
(universe of keys) k1 k4

k1
k4
K
(actual k2 k6
k5 k5 k2 k6
keys)
k8 k7
k3
k7 k3

k8
m–1

142
Hashing with Chaining
Dictionary Operations:
Chained-Hash-Insert (T, x)
Insert x at the head of list T[h(key[x])].
Worst-case complexity – O(1).
Chained-Hash-Delete (T, x)
Delete x from the list T[h(key[x])].
Worst-case complexity – proportional to length of list with
singly-linked lists. O(1) with doubly-linked lists.
Chained-Hash-Search (T, k)
Search an element with key k in list T[h(k)].
Worst-case complexity – proportional to length of list.

143
Analysis on Chained-Hash-Search
Load factor =n/m = average keys per slot.
m – number of slots.
 n – number of elements stored in the hash table.
Worst-case complexity: (n) + time to compute h(k).

 Average depends on how h distributes keys among m slots.


Assume
Simple uniform hashing.
 Any key is equally likely to hash into any of the m slots, independent of
where any other key hashes to.
O(1) time to compute h(k).
Time to search for an element with key k is Q(|T[h(k)]|).
Expected length of a linked list = load factor =  = n/m.

144
Expected Cost of an Unsuccessful Search
Theorem:
An unsuccessful search takes expected time Θ(1+α).

Proof:
Any key not already in the table is equally likely to hash
to any of the m slots.
To search unsuccessfully for any key k, need to search to
the end of the list T[h(k)], whose expected length is α.
Adding the time to compute the hash function, the total
time required is Θ(1+α).

145
Expected Cost of a Successful Search
Theorem:
A successful search takes expected time Θ(1+α).
Proof:
 The probability that a list is searched is proportional to the number of elements
it contains.
 Assume that the element being searched for is equally likely to be any of the n
elements in the table.
 The number of elements examined during a successful search for an element x
is 1 more than the number of elements that appear before x in x’s list.
 These are the elements inserted after x was inserted.
 Goal:
 Find the average, over the n elements x in the table, of how many elements were inserted
into x’s list after x was inserted.

146
Expected Cost of a Successful Search
Theorem:
A successful search takes expected time Θ(1+α).
Proof (contd):
 Let xi be the ith element inserted into the table, and let ki = key[xi].
 Define indicator random variables Xij = I{h(ki) = h(kj)}, for all i, j.
 Simple uniform hashing  Pr{h(ki) = h(kj)} = 1/m

 E[Xij] = 1/m.
 Expected number of elements examined in a successful search is:
1 n  n

E   1   X ij 
 n i 1  j i 1 

No. of elements inserted after xi into the same slot as xi.


147
Proof
1 
– Contd.
n  n
E   1  X ij

 n i 1  j i 1 
1 n  n

  1   E [ X ]
ij 
 (linearity of expectation)
n i 1  j i 1 
1 n  n
1
  1   
n i 1  m
j i 1 

1 n
 1  (n  i)
nm i 1
1  n n

 1  n  i
nm  i 1 i 1 

1  2 n(n  1) 
 1 n  
nm  2 
Expected total time for a successful search
n 1
 1 = Time to compute hash function + Time
2m
 1


 to search
2 2n
= O(2+/2 – /2n) = O(1+ ).
148
Expected Cost – Interpretation
If n = O(m), then =n/m = O(m)/m = O(1).
 Searching takes constant time on average.
Insertion is O(1) in the worst case.
Deletion takes O(1) worst-case time when lists are doubly
linked.
Hence, all dictionary operations take O(1) time on
average with hash tables with chaining.

149
Good Hash Functions
Satisfy the assumption of simple uniform hashing.
Not possible to satisfy the assumption in practice.
Often use heuristics, based on the domain of the keys, to
create a hash function that performs well.
Regularity in key distribution should not affect uniformity.
Hash value should be independent of any patterns that might
exist in the data.
E.g. Each key is drawn independently from U according to a
probability distribution P:
k:h(k) = j P(k) = 1/m for j = 0, 1, … , m–1.
An example is the division method.

150
Keys as Natural Numbers
Hash functions assume that the keys are natural numbers.
When they are not, have to interpret them as natural numbers.
Example: Interpret a character string as an integer expressed
in some radix notation. Suppose the string is CLRS:
ASCII values: C=67, L=76, R=82, S=83.
There are 128 basic ASCII values.
So, CLRS = 67·1283+76 ·1282+ 82·1281+ 83·1280
= 141,764,947.

151
Division Method
Map a key k into one of the m slots by taking the
remainder of k divided by m. That is,
h(k) = k mod m
Example: m = 31 and k = 78  h(k) = 16.
Advantage: Fast, since requires just one division
operation.
Disadvantage: Have to avoid certain values of m.
Don’t pick certain values, such as m=2p
Or hash won’t depend on all bits of k.
Good choice for m:
Primes, not too close to power of 2 (or 10) are good.
152
Multiplication Method
If 0 < A < 1, h(k) = m (kA mod 1) = m (kA – kA) 
where kA mod 1 means the fractional part of kA, i.e., kA –
kA.
Disadvantage: Slower than the division method.
Advantage: Value of m is not critical.
Typically chosen as a power of 2, i.e., m = 2p, which makes
implementation easy.

Example: m = 1000, k = 123, A  0.6180339887…


h(k) = 1000(123 · 0.6180339887 mod 1)
= 1000 · 0.018169...  = 18.
153

You might also like