You are on page 1of 22

CS8391 - DATA STRUCTURES

STUDY MATERIALS

UNIT – II
Queue ADT – Operations – Circular Queue – Priority Queue – deQueue – applications of
queues.

UNIT – III NON LINEAR DATA STRUCTURES – TREES


Tree ADT – tree traversals – Binary Tree ADT – expression trees – applications of trees –
binary search tree ADT –Threaded Binary Trees- AVL Trees – B-Tree – B+ Tree – Heap –
Applications of heap.

PREPARED BY

M.SIVAKUMAR, AP/CSE
SRI ESHWAR COLLEGE OF ENGINEERING,
COIMBATORE - 641202

1
QUEUE ADT

Definition
Queue is a linear data structure where the first element is inserted from one end called REAR and
deleted from the other end called as FRONT
Features:
1. It is an abstract data type
2. It follows First In First Out property
3. It has three components:
i). actual data ii).front iii).rear
3. Insertion is done using rear and deletion is happened using front
Real-time Examples:
 Queue of processes in OS.
 Queue of people at any service point such as ticketing etc.
 Queue of packets in data communication.
 Queue of air planes waiting for landing instructions.
Diagrammatic Representation:

Uses:
 Breadth-first search uses a queue to keep track of the nodes to visit next
 Printers use queues to manage jobs—jobs get printed in the order they're submitted
 Web servers use queues to manage requests—page requests get fulfilled in the order they're
received
 Processes wait in the CPU scheduler's queue for their turn to run

Types of Queue
1. Linear Queue
2. Circular Queue
3. Priority Queue
4. Double Ended Queue [ Dequeue]
Implementation
The queue can be implemented in two ways:
 Array
 Linked list

I . QUEUE [USING ARRAY]


 Queue can be implemented using an array, where the size of an array must be a fixed one
 It uses ‘front’ and ‘rear’ variable for insertion and deletion
Major Operations:
i). Enqueue [Insertion]
ii). Dequeue [Deletion]
iii). Display
Global declaration:
#define MAX 10
int queue [MAX];
int rear = - 1, front = - 1,ele;

2
i). Enqueue
- Check if the queue is full or not.
- If the queue is full, then print overflow.
- If the queue is not full, then increment the rear by 1 and
add the element
Code:
printf(“Enter the element to be inserted:”);
scanf(“%d”, &ele);
if(rear==-1) // If there is not element
{
front=rear=0;
Before Insertion
queue[rear]=ele;
}
else if(rear==MAX-1) // Checks for places
{
printf("\n QUEUE is full.");
return;
}
else // Insert new element using rear
{
rear++;
After Insertion
queue[rear]=ele;
}
ii). Dequeue
- Check if the queue is empty or not.
- If the queue is empty, then print underflow.
- If the queue is not empty, then print the element using ‘front’ and increment the front by 1.
Code:
if(front==-1) // Checks for empty queue
{
printf("QUEUE is Empty.");
return;
}
else if(front==rear) // checks for single element
{
ele=queue[front]; Before Deletion
front=rear=-1;
}
else // Delete an element by incrementing front
{
ele=queue[front];
front++;
} After Deletion
printf("\n Deleted item is : %d.", ele);

iii). Display
- Check if the queue is empty or not
- If the queue is empty, then print ‘Queue is empty”
- If the queue is not empty, then print the element using from front and stop till rear
if(rear==-1)
printf("\nQUEUE is Empty.");
else{
for(i=front;i<=rear;i++)
printf("%d,",queue[i]);
}
3
QUEUE [USING LINKED LIST]
 Queue can be implemented using an linked list, where the size of an queue will be dynamic
 It uses ‘rear’ and ‘front’ variable for insertion and deletion
Major Operations:
i). Enqueue [Insertion]
ii). Dequeue [Deletion]
iii). Display
Global declaration:
struct Node
{
int data;
struct Node *next;
}*front = NULL,*rear = NULL;
i). Enqueue
- Create a new node ‘n’ with given value and set 'n → next' to NULL.
- Check whether queue is Empty (rear == NULL)
- If it is Empty then, set front = n and rear = n.
- If it is Not Empty then, set rear → next = n and rear = n
Code:
struct Node *n;
n = (struct Node*)malloc(sizeof(struct Node));
n->data = value;
n -> next = NULL;
if(front == NULL)
front = rear = n;
else{
rear -> next = n;
rear = n;
} After insertion
Insert 20

ii). Dequeue
- Check whether queue is Empty (front == NULL)
- If it is Empty, then display "Queue is Empty!!! Deletion is not possible!!!"
- If it is Not Empty then, define a Node pointer 'temp' and set it to 'front'
- Then set 'front = front → next' and delete 'temp' Before deletion
Code:
if(front == NULL)
printf("\nQueue is Empty!!!\n");
else{
struct Node *temp = front;
front = front -> next; After deletion
printf("\nDeleted element: %d\n", temp->data);
free(temp);
}
iii). Display
- Check whether queue is empty, if so print as “Queue is empty”
- If it is not, then print the elements from front to rear

4
Code:
if(front == NULL)
printf("\nQueue is Empty!!!\n");
else{
struct Node *temp = front;
while(temp!=NULL){
printf("%d ", temp->data);
temp = temp->next; Output: 10 20 30
}
}

II . CIRCULAR QUEUE
 In a circular queue, all nodes are treated as circular. Last node is connected back to the first node.
 It contains a collection of data which allows insertion of data at the end of the queue and deletion of
data at the beginning of the queue.

Example:
Eating - breakfast, lunch, snacks, dinner -
breakfast….
Days in a week - Sunday - Saturday - Sunday ….
Months in a year - Jan - Dec- Jan

Advantages of Circular Queue:


 It overcomes the limitation of the linear queue.
 The new element is added at the very first position of the queue if the last is occupied and space is
available
 In a linear queue, even though if spaces are available in the front side but it is unable to insert a new
element using a rear, but this problem can be resolved using circular queue.

Major Operations:
i). Enqueue [Insertion]
ii). Dequeue [Deletion]
iii). Display
(i).Enqueue:
 Check whether queue is Full, If it is full then display Queue is full.
 If queue is not full then, check if (rear == SIZE – 1 && front != 0) if it is true then set rear=0 and
insert element
Code:
int ele;
if((front == 0 && rear == SIZE-1) || (front == rear+1))
printf("Queue Overflow \n");
else
{
printf(“Enter the element:”);
5
Before Insertion After Insertion
scanf(“%d”,&x);
if(front == -1)
front = 0;
rear = (rear + 1) % SIZE;
a[rear] = ele;
}
(ii).De-queue:
 Check whether queue is Empty, if so then display queue is empty.
 If queue is not empty then check whether the queue is having single element, if it so then make
rear and front as -1, if not then increment front by 1.
Code:
if (front == -1)
printf("Queue Underflow\n");
else Before Deletion After Deletion
{
printf(“Deletetion elemet is : %d\n",a[front]);
if(front == rear) {
front = -1;
rear = -1;
}
else
front = (front+1) % SIZE;
}
iii). Display
 Check whether queue is Empty, if so then display queue is empty.
 If not, then print all the value from front to rear.
Code:
if (front == -1)
printf("Queue is empty\n");
else
{
for(int i = front; i != rear; i= (i+1) % SIZE)
{
printf(“%d “,a[i]);
} Output: 10 50 20 71
printf(“%d”,a[i]);
}
Applications of Circular Queue
 Memory Management: The unused memory locations in the case of ordinary queues can be
utilized in circular queues.
 Traffic system: In computer controlled traffic system, circular queues are used to switch on the
traffic lights one by one repeatedly as per the time set.
 CPU Scheduling: Operating systems often maintain a queue of processes that are ready to execute
or that are waiting for a particular event to occur.

III. PRIORITY QUEUE


A priority queue is a special queue where:
- Every item in the queue has a priority, and
- Higher-priority items are de-queued before lower-priority items
Uses:
- triaging patients in a hospital, locating the closest available taxi, or just a to-do list
- Operating system schedulers
6
Major Operations:
i). Insertion
ii). Deletion
iii). Display
Global declaration:
typedef struct node
{
int priority;
int info;
struct node *link;
}NODE;
NODE *front = NULL;
(i). Insertion
 Create a new node and then checks whether the queue is empty or not.
 If the queue is empty it adds the node at the first place, else it reaches to the last position and adds
the item there.
Code:
NODE *tmp,*q;
tmp = (NODE *)malloc(sizeof(NODE));
printf(“Enter the new element:”);
scanf(“%d”,&tmp->info);
printf(“\nEnter the priority:”);
scanf(“%d”,&tmp->priority);
*Queue is empty or item to be added has priority more than first item*/
if( front == NULL || priority < front->priority )
{
tmp->link = front;
front = tmp;
}
else
{
q = front;
while( q->link != NULL && q->link->priority <= priority )
q=q->link;
tmp->link = q->link;
q->link = tmp;
}
(ii). Deletion
 Check whether the list is empty, if so then print “Queue is empty”
 If any node exists, it will delete the node.
Code:
NODE *tmp;
if(front == NULL)
printf("Queue Underflow\n");
else
{
tmp = front;
printf("Deleted item is %d\n", tmp->info);
front = front->link;
free(tmp);
}
7
(iii). Display
 Check whether the list is empty, if so then print “Queue is empty”
 If any node exists, then display all the elements
Code:
NODE *ptr;
ptr = front;
if(front == NULL)
printf("Queue is empty\n");
else
{
printf("Queue is :\n");
printf("Priority Item\n");
while(ptr != NULL)
{
printf("%d %d \n", ptr->priority, ptr->info);
ptr = ptr->link;
}
}

IV. DOUBLE ENDED QUEUE [DEQUEUE]


Double Ended Queue is also a Queue data structure in which the insertion and deletion operations are
performed at both the ends (front and rear)

Types of DeQueue
 Input Restricted DeQueue
 Output Restricted DeQueue
In Input Restricted DeQueue , insertion can be done from REAR only, but deletion can be done from
both FRONT and REAR.

In Output Restricted DeQueue, deletion can be done from FRONT only, but insertion can be done
from both FRONT and REAR.

Basic Operations:
i). Insertion_left
ii). Insertion_right
iii).Deletion_left
iv).Deltion_right
v).Display
Global declaration:
# define MAX 10
int deque_arr[MAX];
int left = -1;
int right = -1;

8
(i). Insertion_left
- Check whether the queue is full or not, if so print “Queue is full”
- If not, decrement the front and insert the new element.
Code:
int item;
if(front == 0)
{
printf("Queue Overflow \n");
return;
}
else if (front == -1)
front = 0; rear = 0;
else
front=front-1;
printf(" Enter the element to insert: ");
scanf("%d", & item);
deque_arr [front] = item ;
(ii). Insertion_right
- Check whether the queue is full or not, if so print “Queue is full”
- If not, increment the rear and insert the new element.
Code:
int item;
if(rear == (QSIZE-1))
{
printf("Queue Overflow \n");
return;
}
else if (front == -1)
{
front = 0; rear = 0;
}
else
rear++;
printf(“Enter the element to insert: ");
scanf("%d", &item);
deque_arr [rear] = item ;

(iii). Deletion_left
- Check whether the queue is empty or not, if so print “Queue is empty”
- If not, increment the front and delete the element at left side.
Code:
if(front == -1 && rear ==-1) {
printf("Queue Underflow \n");
return;
}
else {
if(front==rear)
front = rear = -1;
else
front++;
}

9
(iv). Deletion_right
- Check whether the queue is empty or not, if so print “Queue is empty”
- If not, decrement the rear and delete the element at left side.
Code:
if(front == -1 && rear ==-1) {
printf("Queue Underflow \n");
return;
}
else {
if(front==rear)
front = rear = -1;
else
rear--;
}
(v). Display
- Check whether the queue is empty or not, if so print “Queue is empty”
- If not, start to print element from front to rear cursor in an array.
Code:
if(rear == -1 && front == -1) {
printf("Queue is Underflow \n");
}
else
{
printf(“The content from front…:”); Output:
for(int i=front;i<= rear;i++) The content from front 2 3 4
..Rear
printf(“%d ”, deque_arr [i]);
printf(“..Rear”);
}

Applications of DeQueue
 Palindrome Checker
 A Steal job scheduling algorithm
 Undo-redo operation in software

10
UNIT – III
TREE
I . BINARY TREE
 A tree in which every node can have a maximum of two children is called Binary Tree
Example:

Binary Tree Representation


A binary tree data structure is represented using two methods. They are:
 Array Representation
 Linked List Representation
i). Array representation:
 Binary tree using array represents a node which is stored sequentially level by level from left to
right.
 Every empty nodes must have NULL value.

ii). Linked representation:


 Binary tree using linked list represents a node which is stored dynamically level by level from left
to right.
 Since doubly linked list is used, empty children will be NULL.

Basic Operations of Binary Tree


i. Insertion
ii. Traversal – Inorder, Pre-order, Post-Order
iii. Deletion
iv. Search

Global declaration:
struct tree {
int data;
struct node* left;
struct node* right;
};
11
(i). Insertion
- Fill the element from left to right based on root node.
Code:
struct tree *create()
{
struct tree *p;
int x;
printf("Enter data(-1 for no data):");
scanf("%d",&x);
if(x==-1)
return NULL;
p=(node*)malloc(sizeof(node));
p->data=x;
printf("Enter left child of %d:\n",x);
p->left=create();
printf("Enter right child of %d:\n",x);
p->right=create();
return p;
}
(ii). Tree Traversal
a). In-Order Traversal
It performs the following steps starting from the root:
o First left node
o Second root node
o Third right node
Code:
void inorder(struct tree *t)
{
if(t!=NULL)
{
In-Order: D B E A C
inorder(t->left);
printf("\n%d",t->data);
inorder(t->right);
}
}
b). Pre-Order Traversal
It performs the following steps starting from the root:
o First root node
o Second left node
o Third right node
Code:
void preorder(struct tree *t)
{
if(t!=NULL)
{
Pre-Order: A B D E C
printf("\n%d",t->data);
preorder(t->left);
preorder(t->right);
}
}

12
c). Post-Order Traversal
It performs the following steps starting from the root:
o First left node
o Second right node
o Third root node
Code:
void postorder(struct tree *t)
{
if(t!=NULL)
{
Post-Order: D E B C A
postorder(t->left);
postorder(t->right);
printf("\n%d",t->data);
}
}

II . BINARY SEAERCH TREE


A BST is a binary tree of nodes ordered in the following way:
 Each node contains one key (also unique)
 The keys in the left subtree are < (less) than the key in its parent node
 The keys in the right subtree > (greater) than the key in its parent node
 Duplicate node keys are not allowed

Basic Operations of Binary Tree


i. Insertion
ii. Traversal – Inorder, Pre-order, Post-Order
iii. FindMin
iv. FindMax
v. Search
vi. Deletion

Global declaration:
struct tree {
int data;
struct node* left;
struct node* right;
};
(i). Insertion
- If the inserting element is smaller than root, it should be placed in left side
- If not identify the appropriate place at right side of the root node

13
Code:
struct tree* insert(struct tree*root, int x)
{
if(!root)
{
root=(struct tree*)malloc(sizeof(struct tree));
root->info = x;
root->left = NULL;
root->right = NULL;
return root;
}
if(root->info > x)
root->left = insert(root->left, x);
else
{
if(root->info < x) Before insertion of ‘4’ After insertion of ‘4’
root->right = insert(root->right,x);
}
return root;
}
(ii). FindMin
- Traverse till left most end from root node
- Print the element
Code:
void FindMin(struct tree* node) {
struct tree* temp = node;
/* loop down to find the leftmost leaf */ The min value is : 1
while (temp->left != NULL) {
temp=temp->left;
}
printf(“The min value is :%d”,temp->data);
}
(iii). FindMax
- Traverse till right most end from root node
- Print the element
Code:
void FindMax(struct tree* node) {
struct tree* temp = node;
The max value is : 14
/* loop down to find the leftmost leaf */
while (temp->right != NULL)
temp=temp->right;
printf(“The min value is :%d”,temp->data);
}
(iv). Search
- Traverse upto the last level in a given tree
- If searching element is matched, then print “found”, if not “not found”
Code:
struct node* search(struct node* root, int key)
{
// Base Cases: root is null or key is present at root
if (root == NULL || root->key == key)
return root;

14
// Key is greater than root's key
if (root->key < key)
return search(root->right, key);
// Key is smaller than root's key
return search(root->left, key);
}
(v). Deletion
- When we delete a node, we have to take care of the children of the node and also that the property
of a BST is maintained
- There can be three cases in deletion of a node
(a).The node is a leaf - This is the most simple case and here we can delete the node immediately
without giving a second thought.
(b).The node has one child

(c).The node has 2 children - When the node to be deleted has 2 children, we need to choose a
node to be replaced with the node to be deleted such that the property of the binary tree remains
intact

Advantages:
 BST is fast in insertion and deletion etc when balanced.
 Very efficient and its code is easier than link lists.

III. THREADED BINARY TREE


Threaded Binary Tree is also a binary tree in which all left child pointers that are NULL (in Linked list
representation) points to its in-order predecessor, and all right child pointers that are NULL (in Linked
list representation) points to its in-order successor.

15
Why do we need Threaded Binary Tree?
 Binary trees have a lot of wasted space: the leaf nodes each have 2 null pointers. We can use these
pointers to help us in inorder traversals.
 Threaded binary tree makes the tree traversal faster since we do not need stack or recursion for
traversal
Types of threaded binary trees:
1. Single Threaded or One way threaded binary tree
 The empty left child field of a node can be used to point to its inorder predecessor.
 Similarly, the empty right child field of a node can be used to point to its in-order successor.
 Such a type of binary tree is known as a one way threaded binary tree.
 A field that holds the address of its in-order successor is known as thread
2. Double Threaded or Two way threaded binary tree
 A field that holds the address of its inorder successor or predecessor is known as thread.
 The empty left child field of a node can be used to point to its inorder predecessor.
 Similarly, the empty right child field of a node can be used to point to its inorder successor.

How to convert binary tree into threaded binary tree?


To convert a binary tree to threaded binary tree, we need to point all NULL right pointers to inorder
successor of that node. The idea is to perform inorder traversal of the binary tree and pass information
about previous visited node along with the node.Now if current node has a NULL right child, we set right
child of its previous node to point to it.

IV. EXPRESSION TREE


 It is a special type of binary tree in which the leaf nodes are operands and the interior nodes are
operators
 Like binary tree: it uses in-order, pre-order and post-order for traversing
Example:

16
Construction of Expression Tree:
Now for constructing expression tree we should use a stack. We loop through input expression and do
following for every character.
1) If character is operand push that into stack
2) If character is operator pop two values from stack make them its child and push current node again.
At the end only element of stack will be root of expression tree.
Example: a b + c d e + * *

Read ‘a’ then ‘b’ and push into stack

Read ‘+’. Pop two operand and form a tree and


push again into stack

Read ‘+’. Pop two operand and form a tree and


Read ‘c’, ‘d’,’e’ and push into stack one by one
push again into stack

Read ‘*’. Pop two operand and form a tree and Read ‘*’. Pop two operand and form a tree and push
push again into stack again into stack

Note: Inorder traversal of expression tree produces infix version of given postfix expression (same
with preorder traversal it gives prefix expression)

17
V. AVL TREE [Adelson, Velskii, and Landi ]
AVL tree is a binary search tree in which the difference of heights of left and right subtrees of any node is
less than or equal to one. (-1, 0,1)
Balance factor of a node is the difference between the heights of the left and right subtrees of that node.
The balance factor of a node is calculated either height of left subtree - height of right subtree (OR) height
of right subtree - height of left subtree
Example:

AVL Rotations
To balance itself, an AVL tree may perform the following four kinds of rotations −
 Single left rotation
 Single right rotation
 Double Left-Right rotation
 Double Right-Left rotation
(i). Single left rotation
- If a tree becomes unbalanced, when a node is inserted into the right subtree of the right subtree,
then we perform a single left rotation

(ii). Single right rotation


- If a tree becomes unbalanced, when a node is inserted into the left subtree of the left subtree,
then we perform a single left rotation

(iii). Double Left-Right rotation


- A node has been inserted into the right subtree of the left subtree. This makes an unbalanced
node.

18
We first perform the left rotation on the left We shall now right-rotate the tree, finally

subtree of C. This makes A, the left subtree of B. balanbed tree is obtained

(iv). Double Right-Left rotation


- A node has been inserted into the left subtree of the right subtree. This makes an unbalanced
node

First, we perform the right rotation along C node, We shall now left-rotate the tree, finally balanbed
making C the right subtree of its own left subtree tree is obtained
B. Now, B becomes the right subtree of A.

AVL Tree Construction: 50, 25, 10, 5, 7, 3, 30, 20, 8, 15

19
Operations on AVL Trees
The following operations are performed on AVL Trees:
 Search
 Insertion
 Deletion

VI. B - TREE
 B Tree is a specialized m-way tree.
 It is a self-balanced search tree in which every node contains multiple keys and has more than two
children.
Properties:
 Every node in a B-Tree contains at most m children.
 Every node in a B-Tree except the root node and the leaf node contain at least m/2 children.
 The root nodes must have at least 2 nodes.
 All leaf nodes must be at the same level.
Example: B-tree with Order = 4

Operations performed on B Tree


i. Insertion in B-Tree
ii. Deletion from B-Tree
(i). Insertion in B-Tree
 There are basically two cases for inserting the key that are:
- Node is not full
- Node is already full
 If the leaf node in which the key is to be inserted is not full, then the insertion is done in the node.
 If the node were to be full then insert the key in order into existing set of keys in the node, split the
node at its median into two nodes at the same level, pushing the median element up by one level.

Create a B-Tree: 5,9,3,7,1,2,8,6,0,4 [ Order = 4]


Order = 4 [ we can accommodate only 3 nodes]

20
21
(ii). Deletion from B Tree
Deletion of the key also requires the first traversal in B tree, after reaching on a particular node two
cases may be occurred that are:
1. Node is leaf node
2. Node is non leaf node

22

You might also like