Unit II
Unit II
Linked Lists
Even if the array is dynamically allocated, an estimation of the maximum size of the list is required which
wastes lot of space if not used. Insertion and deletion are expensive because insertion at first requires first
pushing the entire array down one spot to make a room, similarly deletion requires pushed up the list.
To avoid the disadvantages of arrays introduced a new concept called linked list, which is not stored
in a contiguously locations. Linked list is also called as self-referential class or one-way list.
The linked list consists of a series of structures, which are not necessarily adjacent in memory. Each
structure contains the element and a pointer to a structure containing its successor. The Previous element to
the tail of the list is called its predecessor. Clearly head does not have a predecessor and tail does not have
successor. We call this the Next pointer.
The last cells Next pointer points to NULL. Combination data and pointer to next structure is also
called as node.
1. Create a list
2. Search for an element in a list
3. Delete an element from a list ( at beg, at end, at given location)
4. Add an element at a specified location of a list (at beg, at end, at given location).
5. Sort a list
6. Print a list
7. Determine the size or no of elements in a list
A list can be implemented statistically or dynamically using an array index or pointers respectively.
In ‘C’
struct Node {
Element_type data;
struct Node *next;
}
struct Node *head;
We can form a linked list using pointers the structure of the list may be as shown below.
10 20 30 NULL
10 3000 20 4000 30 0
UNIT II
DATA STRUCTURES
Some times it is convenient to traverse lists backwards. The standard implementation does not help
here. The cost of this is an extra link, which adds to the space requirements and also doubles the cost of
instructions and deletions because there are more pointers to fix. On the other hand it simplifies deletion,
because you no longer have to refer to a key by using a pointer to the previous cell.
NUL A1 A2 A3 NUL
L L
Circular Linked List:
A Popular Convention to have the last cell keep a pointer back to the first. It can be done with or
without header.
A1 A2 A3
#include<stdio.h>
#include<conio.h>
#include<alloc.h>
struct node
{
int data;
struct node *next;
};
UNIT II
DATA STRUCTURES
void main()
{
int ch;
node *start=NULL;
while(1)
{
clrscr();
printf("\n1.Create\n2.Insert at beg\n3.Insert at end\n4.Insert at loc\n");
printf("\n5.Del at Beg\n6.Del at Loc\n7.Del at End\n8.Show\n9.Exit");
printf("Enter your choice...");
scanf("%d",&ch);
switch(ch)
{
case 1:
start = create(start); break;
case 2:
start = insertbeg(start);break;
case 3:
insertend(start);break;
case 4:
insertloc(start); break;
case 5:
start = delbeg(start);break;
case 6:
delloc(start);break;
case 7:
delend(start); break;
case 8:
show(start); getch();break;
case 9:
default:
UNIT II
DATA STRUCTURES
return;
}
}
}
while(ch=='y')
{
temp = (node *) malloc(sizeof(node));
printf("\nEnter data : ");
scanf("%d",&temp->data);
temp->next = NULL;
if(t==NULL)
t = temp;
else
{
p = t;
while(p->next!=NULL)
p = p->next;
p->next = temp;
}
printf("\n Wish to insert one more?");
ch = getchar();
}
return t;
}
void show(node *t)
{
node *p;
for(p = t;p!=NULL;p=p->next)
printf("%d->",p->data);
printf("null\n");
}
UNIT II
DATA STRUCTURES
return t;
}
void insertloc(node *t)
{
node *p,*k;
int loc,i;
p = (node *)malloc(sizeof(node));
printf("Enter data & location");
scanf("%d%d",&p->data,&loc);
k = t;
for(i=1;i<loc;i++)
k = k->next;
p->next = k->next;
k->next = p;
}
k = t;
while(k->next!=NULL)
k = k->next;
k->next = p;
}
p = t; k = t->next;
while(k->next!=NULL)
UNIT II
DATA STRUCTURES
{
p = p->next;
k = k->next;
}
p->next = NULL;
free(k);
}
p = t; k = t->next;
printf("\nEnter location : ");
scanf("%d",&loc);
for(i=1;i<loc;i++)
{
p = p->next;
k = k->next;
}
p->next = k->next;
free(k);
}
Stack
The stack is a data structure that is very frequently used in computing as a kind of temporary storage. It is a
list of elements to which additions and deletions can only be made at one end-the top. Consequently, the
stack becomes a last-in-first-out (LIFO) data structure; the last element added is the first to be removed. When
we add an item to the top of the stack, it is called a PUSH operation and when we remove an item from the
top, it is called a POP operation. The stack data structure maintains a stack pointer always pointing to its top.
After pushing an item, the stack pointer moves up to point always to the last item added. Similarly, after
popping an item, the stack pointer moves down to the next last item in the stack.
UNIT II
DATA STRUCTURES
Stack Model
3 Top
2
1
4 Top
3
2
1
3 Top
2
1
Code is here:
#include<stdio.h>
#include<conio.h>
#define MAX 5
UNIT II
DATA STRUCTURES
return;
}
else
{
printf("\nEnter an item : ");
scanf("%d",&d);
stk[++(*top)] = d;
}
}
printf("\n\n");
while(i>=0)
printf("%4d",stk[i--]);
printf("\n");
}
void main()
{
int ch;
int stk[MAX];
int top = -1;
clrscr();
while(1)
{
printf("\nSTACK OPERATIONS\n----------------\n1.Push\n2.Pop\n3.Show\n");
printf("4.Exit\n\nEnter your chioce...");
scanf("%d",&ch);
switch(ch)
UNIT II
DATA STRUCTURES
{
case 1:
push(stk,&top);
break;
case 2:
pop(stk,&top); break;
case 3:
show(stk,&top); break;
case 4:
default:
return;
}
}
}
Code is here:
#include<stdio.h>
#include<conio.h>
#include<alloc.h>
struct dnode
{
int data;
struct dnode *prev,*next;
};
void main()
{
int ch;
dnode *start=NULL;
UNIT II
DATA STRUCTURES
while(1)
{
clrscr();
printf("\n1.Create\n2.Insert at beg\n3.Insert at end\n4.Insert at loc\n");
printf("\n5.Del at Beg\n6.Del at Loc\n7.Del at End\n8.Show\n9.Exit");
printf("\n\nEnter your choice...");
scanf("%d",&ch);
switch(ch)
{
case 1:
start = create(start); break;
case 2:
start = insertbeg(start);break;
case 3:
insertend(start);break;
case 4:
insertloc(start); break;
case 5:
start = delbeg(start);break;
case 6:
delloc(start);break;
case 7:
delend(start); break;
case 8:
show(start); getch();break;
case 9:
default:
return;
}
}
}
while(ch=='y')
{
temp = (dnode *) malloc(sizeof(dnode));
printf("\nEnter data : ");
scanf("%d",&temp->data);
temp->prev = temp->next = NULL;
if(t==NULL)
UNIT II
DATA STRUCTURES
t = temp;
else
{
p = t;
while(p->next!=NULL)
p = p->next;
p->next = temp;
temp->prev = p;
}
fflush(stdin);
printf("\n Wish to insert one more?");
ch = getchar();
}
return t;
}
for(p = t;p->next!=NULL;p=p->next)
printf("%d->",p->data);
printf("%d->null\n",p->data);
for(;p!=NULL;p=p->prev)
printf("%d->",p->data);
printf("null\n");
p = (dnode *)malloc(sizeof(dnode));
printf("Enter data & location");
UNIT II
DATA STRUCTURES
scanf("%d%d",&p->data,&loc);
k = t;
for(i=1;i<loc;i++)
k = k->next;
p->next = k->next;
k->next->prev = p;
k->next = p;
p->prev = k;
}
k = t;
while(k->next!=NULL)
k = k->next;
k->next = p;
p->prev = k;
}
p = t;
t = t->next;
t->prev = NULL;
free(p);
return t;
}
p = t; k = t->next;
while(k->next!=NULL)
{
p = p->next;
UNIT II
DATA STRUCTURES
k = k->next;
}
p->next = NULL;
free(k);
}
p = t; k = t->next;
printf("\nEnter location : ");
scanf("%d",&loc);
for(i=1;i<loc;i++)
{
p = p->next;
k = k->next;
}
p->next = k->next;
k->next->prev = p;
free(k);
}
The first implementation of a stack uses a single linked list. We perform a push by inserting at the
front of the list. We perform a pop by deleting the element at the front of the list. A top operation merely
examines the element at the front of the list, returns its value.
Ex:
Shows a sample Stack
top
3 2 1 NULL
4 3 2 1 NULL
When you Pop, the Stack would be
UNIT II
DATA STRUCTURES
top
3 2 1 NULL
Code is here:
Applications of Stacks:
1. Compilers will take the help of stack for checking syntax errors (Symbol Balancing)
2. Stacks were used in evaluating postfix expressions (Reverse polish notation).
3. Stacks are used in conversion of infix expressions to postfix expressions.
4. Stack for matching brackets in an expression.
5. Stacks were used in function call.
i.e. When there is a function call, all the important information that needs to be saved, such as register
values and the return addresses are saved onto the stack. The information saved is called either an activation
record or stack frame.
Conversions:
#include<stdio.h>
#include<conio.h>
#define MAX 7
UNIT II
DATA STRUCTURES
void main()
{
char infix[20],post[20];
clrscr();
conversion(infix,post);
getch();
}
j = 0;
for(i=0;in[i]!='\0';i++)
{
ch = in[i];
if(isalpha(ch))
post[j++] = ch;
else
if(ch=='(')
stk[++top] = ch;
else
if(ch==')')
{
while(stk[top]!='(')
post[j++] = stk[top--];
top--;
}
else
{
while(pcd(stk[top]) >= pcd(ch))
post[j++] = stk[top--];
UNIT II
DATA STRUCTURES
stk[++top] = ch;
}
}
while(top>-1)
post[j++] = stk[top--];
post[j] = '\0';
}
#include<stdio.h>
#include<conio.h>
UNIT II
DATA STRUCTURES
#define MAX 7
void main()
{
char postfix[20];
clrscr();
getch();
}
i = 0;
while(post[i]!='\0')
{
ch = post[i];
if(isdigit(ch))
stk[++top] = (float) ch-'0';
else
{
b = stk[top--];
a = stk[top--];
c = calculate(a,b,ch);
stk[++top] = c;
}
i++;
}
return stk[top--];
}
UNIT II
DATA STRUCTURES
Queue
Like Stacks, Queues are lists. With a queue, however, insertion is done at one end called rear end, where as
deletion is performed at the other end called front end. Some times it is called FIFO (First in First out) List.
The basic operations on a queue are Enqueue, which inserts an element at the end of the list (called
the rear), and Dequeue, which deletes the elements at the start of the list.
Model of a Queue is
Dequeue(Q) Enqueue(Q)
Queue Q
After Create
0 1 2 3 4
Front = 0, Rear = 0
5 7 9
0 1 2 3 4
Front Rear
After an Dequeue operation
7 9
0 1 2 3 4
Front Rear
UNIT II
DATA STRUCTURES
But there is one potential problem with the above implementation after some Enqueue operation the Queue
appears to be full. (Suppose rear = 4 and front = 2 for 5 cell queue the queue appears to be full but not). Then
you cannot insert further till the queue is empty.
The Simple solution is that whenever front and rear gets to the end of the array, it is wrapped around to the
beginning. This is known as circular Queue.
Applications of queues:
1. Uses of Queues in operating systems: Operating system maintains several queues like ready queue, device
queue etc. for handling multiple processes.
3. A Whole branch of mathematics, known as queuing theory, deals with computing, probabilistically, how
long users expect to wait on a line, how long the line gets, and other such questions.
#include<stdio.h>
#include<conio.h>
#define MAX 5
int q[MAX];
int front,rear;
void enqueue()
{
int d;
if(rear==MAX-1)
{
printf("\n Queue is FULL\n");
return;
}
else
{
printf("\nEnter an item : ");
scanf("%d",&d);
q[++rear] = d;
}
}
void dequeue()
{
if(front==rear+1)
UNIT II
DATA STRUCTURES
{
printf("\nQueue is Empty !!\n");
return;
}
else
printf("\nDeleted item : %d\n",q[front++]);
}
void show()
{
int i = front;
printf("\n\n");
while(i<=rear)
printf("%4d",q[i++]);
printf("\n");
}
void main()
{
int ch;
front = 0;
rear = -1;
while(1)
{
printf("\nQUEUE OPERATIONS\n\n1.Enqueue\n2.Dequeue\n3.Show\n");
printf("4.Exit\n\nEnter your chioce...");
scanf("%d",&ch);
switch(ch)
{
case 1:
enqueue(); break;
case 2:
dequeue(); break;
case 3:
show(); break;
case 4:
default:
return;
}
}
}
UNIT II
DATA STRUCTURES
Trees
Def: A tree is a collection of nodes. A Tree consists of a distinguished node r, called the root, and zero or
more nonempty (sub) trees T1, T2…Tk each of whose roots are connected by a directed edge from r.
The root of each subtree is said to be child of r, and r is the parent of each sub root.
A Tree of n nodes will consist of n-1 edges. Node with no children is called Leaf. Nodes with
same parent are called Siblings. A Path from n1 to nk is defined as a sequence of nodes n1,n2,----,nk such that
ni is the parent of ni + 1 for 1 <= i<= k. the Length of the path is the no of edges on the path. There is a path
of length zero from every node to itself.
Note:- In a tree there is only one path from root to each node.
For any node ni, the depth of ni is the length of the unique path from the root is at depth 0.
The Height of ni is the longest path from ni to a leaf. If there is path from n1 to n2, there n1 is an ancestor of n2
and n2 is a descendent of n1. If n1 n2 then n1 is a proper ancestor of n2 and n2 is a proper descendent of n1.
Applications of Trees
1) Help analyze electrical circuits and to represent the structure of mathematical formulas.
2) Trees are used to represent the syntactic structure of source programs in compilers.
3) Trees are used in expression evaluation
4) Trees are used in storing records into the database (e.g. B-Trees). This improves the performance of data
storage and retrieval.
5) Trees are used in maintaining the directory and file system within the operating systems.
6) Used to represent web page structures.
UNIT II
DATA STRUCTURES
struct Tree_Node
{
Element_Type data;
Struct Tree_Node *First_Child;
struct Tree_Node *Next_Silding;
. . . .
};
A Sample Tree:
A
B D E
C
F
I
G
H
Binary Trees:
A Binary tree is a tree in which no node can have more than two children. The first subset contains a single
element called the ‘root’ of the tree. The other two subsets themselves binary tree, called the ‘left’ and ‘right’
sub trees of the original tree.
If every non-leaf node in a binary tree has nonempty left and right sub trees, the tree is termed a
‘strictly binary tree’. A ‘complete binary tree’ of depth d is the strictly binary tree all of whose leaves are at
level d.
A A
Ex:
B
B C
C
D D
E
E
UNIT II
DATA STRUCTURES
A binary search tree is a binary tree in which all elements stored in the left sub tree of any node X are all less
than the element stored at X, and all elements stored in the right sub tree of X are greater than the element
stored at X. Minimum element of the BST is the left leaf node and Maximum element of the BST is the right
most leaf node. Searching of any element is very fast. The average depth of a binary search tree is O(log n).
Ex:
2 8
1 4
To insert any element first check whether this element is already exists in a tree if the element is not found,
then check whether the element is greater than the root or less than the root if the element is greater than
the root then it moves towards right words if it is less than the root then it moves left words, this process
continues recursively and finding a correct location and insert an element.
After Inserting 5
6
5<6 6
2 8
5>2 2 8
5>4 1 4
1 4
Inserted 3
3 5
UNIT II
DATA STRUCTURES
Once we have found the node to be removed, we need to consider several possibilities
1. If node is a leaf, it can be deleted immediately
2. If the node has one child, the node can be removed after its parent adjusts
a pointer to bypass the node. Notice that the removed node is now
Unreferenced and can be deleted only if a pointer to it has been saved.
3. The complicated case is when a node has two childrens the general strategy is to replace the key of this
node will the smallest key of the right sub tree and remove that smallest key from the right sub tree.
Ex:
Consider a BST
6
2 8
1 4
3
3.
5
6
Minimum of
8
Right sub Tree 3
1 4
3.
5
Where 3 is the minimum of sub tree and 3 is deleted from right sub tree.
Let T be a binary tree. There are different methods that differ in the order in which they visit the
nodes. The three different traversal methods are
(1) Inorder,
(2) Preorder,
UNIT II
DATA STRUCTURES
(3) Postorder
Inorder Traversal:
B C
D E F
The inorder traversal of the given binary tree is,
D B E A F C
Preorder Traversal:
#include<stdio.h>
#include<conio.h>
#include<process.h>
UNIT II
DATA STRUCTURES
struct node
{
int data;
node *left,*right;
};
UNIT II
DATA STRUCTURES
void main()
{
int ch;
int data;
node *t=NULL;
clrscr();
while(1)
{
cout<<"\n\nM A I N M E N U\n- - - - - - - -\n";
cout<<"\n1. Insert \n 2. Preorder \n 3. Inorder \n 4. Postorder\n";
cout<<"\n5. Exit\n Enter ur choice :";
cin>>ch;
switch(ch)
{
case 1:
printf("\nEnter data :");
scanf("%d",&data);
t = insert(t,data);
break;
case 2:
printf("\n\n");
UNIT II
DATA STRUCTURES
preorder(t);break;
case 3:
printf("\n\n");
inorder(t);break;
case 4:
printf("\n\n");
postorder(t);break;
case 5:
default:
exit(0);
}
}
Graphs
A Graph G consists of a set V of vertices (Nodes) and a set of edges (arcs)E. We write G = (V, E). V is a finite
and non empty set of vertices. E is a set of pairs of vertices called edges.
An edge e = (v, w) is a pair of vertices v and w, and is said to be incident with v and w. Nodes v and w
are called as endpoints of e, and u and v are said to be adjacent nodes or neighbors. Ex: An example graph G
A B
C
V (G) = { A, B, C }
E (G) = { (A, B) (A, C) (B, C) }
Representation of Graphs:
1. Adjacency Matrix
2. Adjacency Lists
The Choice of representative depends on the application and function to be performed on the graph.
Adjacency Matrix:
The Adjacency Matrix A for a graph G = (V, E) with n vertices, is an n x n Matrix if bits, such that A
UNIT II
DATA STRUCTURES
Ex:
Let us consider a graph
1 2
4 3
1 2 3 4
A= 1 0 1 0 1
2 0 0 1 0
3 0 0 0 0
4 0 0 1 0
In this representation, we store a graph as a linked structure. We store all the vertices in a list and
then for each vertex, we have a linked list of the adjacent vertices.
Ex:
Let us consider a Graph
1 2
4 3
1
2 4 NULL
2
3 NULL
UNIT II
NULL
DATA STRUCTURES
Graph Traversals:
Given Undirected graph G and a vertex V in V(G) we are interested in visiting all vertices in G that are
reachable from V1 we shall look at two ways of doing this
1. Depth first Search
2. Breadth first Search
Depth first Search of an undirected graph proceeds as follows. The start Vertex V is visited. Next an
unvisited Vertex W adjacent to V is
selected and a depth first search from W initiated. When a vertex U is reached such that all its adjacent vertices
have been visited. We back up to the last vertex visited which has an unvisited Vertex W adjacent to it and
initiate a depth first search from W. The search terminates when no unvisited vertex can be reached from any
of the visited ones.
Pseudo Code
Void DFS(Vertex V)
{
visited[v] = True;
for each Vertex W adjacent to V
if(! Visited[W])
DFS(W);
}
Ex:
A
For the Given Graph
A
B
B D E
C
UNIT II
C
D E
DATA STRUCTURES
Breadth-First-Search
Starting at vertex V and marking it an visited. BFS differs from Depth first search in that all unvisited
vertices adjacent to V are visited next. Then unvisited vertices adjacent to these vertices are visited and so on.
Pseudo code
Void BFS(Vertex V)
{
initialize Q to be Empty //Q is a Queue
while(1)
{
for each vertex W adjacent to V
if(visited[W] = false)
{
Enqueue(Q, W);
Visited[W] = True;
}
if(Q is Empty)
return;
V = Dequeue(Q);
}
}
Ex:
Let the given graph be The BFS of the given graph is
A
A
B D E
B D E
C
UNIT II
C
DATA STRUCTURES
Here dashed line indicates Back edges which are not really part of the tree but are available in graph.
UNIT II