Data Structures 8.1 Introduction To Data Structures
Data Structures 8.1 Introduction To Data Structures
Data structure
Linear Nonlinear
In the linear data structures , data can be processed one by one sequentially. A linear data structure contains the
following types of data structures -
1. Array
2. Linked list
3. Stack and Queues
A data structure in which insertion and deletion of data is not possible in a linear fashion is called a nonlinear data
structure as follows
1. Tree
2. Graphs
8.2 Abstract data type
A mathematical entity consisting of a set of values (the carrier set) and a collection of operations that
manipulate them. For example, the Integer abstract data type consists of a carrier set containing the
positive and negative whole numbers and 0, and a collection of operations manipulating these values,
such as addition, subtraction, multiplication, equality comparison, and order comparison.
Abstraction
To abstract is to ignore some details of a thing in favor of others. Abstraction is important in problem
solving because it allows problem solvers to focus on essential details while ignoring the inessential, thus
simplifying the problem and bringing to attention those aspects of the problem involved in its solution.
Abstract data types are important in computer science because they provide a clear and precise way to
specify what data a program must manipulate, and how the program must manipulate its data, without
regard to details about how data are represented or how operations are implemented. Once an abstract
data type is understood and documented, it serves as a specification that programmers can use to guide
their choice of data representation and operation implementation, and as a standard for ensuring program
correctness.
A realization of an abstract data type that provides representations of the values of its carrier set and
algorithms for its operations is called a data type. Programming languages typically provide several built-
in data types, and usually also facilities for programmers to create others. Most programming languages
provide a data type realizing the Integer abstract data type, for example. The carrier set of the Integer
abstract data type is a collection of whole numbers, so these numbers must be represented in some way.
Programs typically use a string of bits of fixed size (often 32 bits) to represent Integer values in base two,
with one bit used to represent the sign of the number. Algorithms that manipulate these strings of bits
implement the operations of the abstract data type. See Algorithm, Programming languages
Realizations of abstract data types are rarely perfect. Representations are always finite, while carrier sets
of abstract data types are often infinite. Many individual values of some carrier sets (such as real
numbers) cannot be precisely represented on digital computers. Nevertheless, abstract data types
provide the standard against which the data types realized in programs are judged.
Usefulness
Such specifications of abstract data types provide the basis for their realization in programs.
Programmers know which data values need to be represented, which operations need to be
implemented, and which constraints must be satisfied. Careful study of program code and the appropriate
selection of tests help to ensure that the programs are correct. Finally, specifications of abstract data
types can be used to investigate and demonstrate the properties of abstract data types themselves,
leading to better understanding of programs and ultimately higher-quality software. See Computer
programming, Software engineering
In a linked list, the elements of the list are stored somewhere in the memory rather that in contiguous
blocks. All the elements of the list are referred to by the link between them. A linked list is a sequence of
data elements in which each element in the sequence points to it's successor. In an array the index refers
the address of the location while in linked list every node contains a pointer which holds the address of
the next node. A linked list is defined as collection of nodes.
Each node has two parts:-
• Data
• Next address (pointer to the next node)
The data field contains the actual element of the list. The next address field contains the address of the
next node in the list. Such an address which is used to access the address of a particular node is called a
pointer. Another pointer variable which points the structure is called structure pointer or external pointer.
The entire linked list is accessed by an external pointer that points the first node in the list. The next
address field of the last node in a linked list contains null.
This null is used to signal the end of a linked list.
The following figure illustrates a linked list.
Data
Address
Consider the following example to illustrator the concept of linking. Suppose we define a structure as
follows
struct linked_list
{
float age;
struct linked_list *next;
}
struct Linked_list node1,node2;
this statement creates space for nodes each containing 2 empty fields
node1
node1.age
node1.next
node2
node2.age
node2.next
The next pointer of node1 can be made to point to the node 2 by the same statement.
node1.next=&node2;
This statement stores the address of node 2 into the field node1.next and this establishes a link between
node1 and node2 similarly we can combine the process to create a special pointer value called null that
can be stored in the next field of the last node
If head is created then we can add the element to tail otherwise then is’t a head
Head Data
Next
void add( )
{ struct node *temp;
temp=(struct node *) malloc(sizeof(struct node));
printf("\ntotal no of nodes are in list %d\n",count);
printf("\n enter any no:");
scanf("%d",&tempdata);
tempnext=NULL;
if(head = = NULL)
head=tail=temp;
else
{
tailnext=temp;
tail=temp;
}
count++;
}
Inserting element
Inserting the element before the element mean specify the position.
1. If position is Head next of the new element is head and Head is know new element.
2. If position is end of the node then the new element is added at end of the list, I.e next of the last node is
new node then next of the new node is NULL
Head Data
New Next
void insert( )
{
void after( );
void before( );
int ch;
printf("\n Inserting a node ");
printf("\n 1. Insert after a node.");
printf("\n 2. Insert before a node.");
printf("\n choice :");
scanf("%d",&ch);
switch(ch)
{ case 1 : after( ); break;
case 2 : before( ); break;
default : printf("\n S.L.L. Implementation ");
getch( );
}
}
void after( )
{
struct node *t,*p;
int i,pos;
t=(struct node *) malloc(sizeof(struct node));
printf("\n total no of nodes are in list %d\n",count);
printf("\n enter the position to insert");
scanf("%d",&pos);
printf("\n enter any no:");
scanf("%d",&tdata);
tnext=NULL;
if(pos = = count)
{
tailnext=t; tail=t;
}
else
{ p=head;
for(i=1;i<pos;i++)
p=pnext;
tnext=pnext;
pnext=t;
}
count++;
}
void before( )
{ struct node *t,*p,*q;
int i,pos;
t=(struct node *) malloc(sizeof(struct node));
printf("\ntotal no of nodes are in list %d\n",count);
printf("\nenter the position to insert");
scanf("%d",&pos);
printf("\nenter any no:");
scanf("%d",&tdata);
tnext=NULL;
p=head;
if(pos = = 1)
{
tnext=p; head=t;
}
else
{ for(i=1;i<pos-1;i++)
p=pnext;
q=pnext;
t next =q; p next =t;
}
count++;
}
Deleting element
Similarly, we have functions for removing the node after a given node, and for removing a node from the
beginning of the list. The diagram demonstrates the former. To find and remove a particular node, one
must again keep track of the previous element.
void del( )
{
struct node *p,*q;
int pos,i;
printf("\n total no of nodes are in list %d\n", count);
if(count = = 0)
printf(“\n Empty S.L.L.”);
else
{
printf("\n enter the position to delete :"); scanf("%d",&pos);
p=head;
if(pos = = 1)
{ q=p next; p next = NULL;
head=q; free(p);
}
else
{ for(i=1;i<pos-1;i++)
p=p next;
q=p next;
if(pos = = count)
{
p next =NULL;
tail=p; free(q);
}
else
{
p next =q next;
q next =NULL;
free(q);
}
}
count--;
}
Write a C program that uses functions to performing following operations on singly linked list:
i) Creation ii) Insertion iii) Deletion iv) Traversal
_______________________________________________________________________________
#include<stdio.h>
#include<alloc.h>
#include<conio.h>
struct node
{
int data;
struct node *next;
};
struct node *head,*tail;
int count=0;
void main( )
{
void display( ); void insert( );
void add( ); void del( );
int opt;
head=tail=NULL;
while(1)
{ clrscr( );
printf(" 1.add.");
printf("\n 2.display.");
printf("\n 3.insert.");
printf("\n 4.del.");
printf("\n 5.exit.");
printf("\n \n choice:");
scanf("%d",&opt);
switch(opt)
{ case 1 : add( ); break;
case 2 : display( ); break;
case 3 : insert( ); break;
case 4 : del( ); break;
case 5 : exit( );
default : printf("\n S.L.L. Implementation");
getch( );
}
}
}
void add( )
{ struct node *temp;
temp=(struct node *) malloc(sizeof(struct node));
printf("\ntotal no of nodes are in list %d\n",count);
printf("\n enter any no:");
scanf("%d",&tempdata);
tempnext=NULL;
if(head = = NULL)
head=tail=temp;
else
{
tailnext=temp;
tail=temp;
}
count++;
}
void display( )
{ struct node *t;
printf("\n total no of nodes are in list %d\n",count);
if(count = = 0)
printf(“Empty S.L.L.”);
else
{ t=head;
while(t)
{
printf("%d ",tdata);
t=tnext;
}
}
getch( );
}
void insert( )
{
void after( );
void before( );
int ch;
printf("\n Inserting a node ");
printf("\n 1. Insert after a node.");
printf("\n 2. Insert before a node.");
printf("\n choice :");
scanf("%d",&ch);
switch(ch)
{ case 1 : after( ); break;
case 2 : before( ); break;
default : printf("\n S.L.L. Implementation ");
getch( );
}
}
void after( )
{
struct node *t,*p;
int i,pos;
t=(struct node *) malloc(sizeof(struct node));
printf("\n total no of nodes are in list %d\n",count);
printf("\n enter the position to insert");
scanf("%d",&pos);
printf("\n enter any no:");
scanf("%d",&tdata);
tnext=NULL;
if(pos = = count)
{
tailnext=t; tail=t;
}
else
{ p=head;
for(i=1;i<pos;i++)
p=pnext;
tnext=pnext;
pnext=t;
}
count++;
}
void before( )
{ struct node *t,*p,*q;
int i,pos;
t=(struct node *) malloc(sizeof(struct node));
printf("\ntotal no of nodes are in list %d\n",count);
printf("\nenter the position to insert");
scanf("%d",&pos);
printf("\nenter any no:");
scanf("%d",&tdata);
tnext=NULL;
p=head;
if(pos = = 1)
{
tnext=p; head=t;
}
else
{ for(i=1;i<pos-1;i++)
p=pnext;
q=pnext;
t next =q; p next =t;
}
count++;
}
void del( )
{
struct node *p,*q; int pos,i;
printf("\n total no of nodes are in list %d\n",count);
if(count = = 0)
printf(“\n Empty S.L.L.”);
else
{
printf("\n enter the position to delete :");
scanf("%d",&pos);
p=head;
if(pos = = 1)
{ q=p next; p next = NULL;
head=q; free(p);
}
else
{ for(i=1;i<pos-1;i++)
p=p next;
q=p next;
if(pos = = count)
{
p next =NULL;
tail=p; free(q);
}
else
{
p next =q next;
q next =NULL;
free(q);
}
}
count--;
}
INPUT:
1. add
2. display
3. insert
4. delete
5. exit
choice :1
OUTPUT:
total no of nodes are in list 0
enter any no: 10
A linked list is a dynamic data structure and therefore the size of the linked list can grow or shrink in size
during execution of the program. A linked list does not require any extra space therefore it does not waste
extra memory. It provides flexibility in rearranging the items efficiently.
The limitation of linked list is that it consumes extra space when compared to a array since each node
must also contain the address of the next item in the list to search for a single item in a linked list is
cumbersome and time consuming.
Types of linked list:
There are different kinds of linked lists they are
Linear singly linked list
Circular singly linked list
Two way or doubly linked list
Circular doubly linked list.
Applications of linked lists:
Linked lists concepts are useful to model many different abstract data types such as queues stacks and
trees. If we restrict the process of insertions to one end of the list and deletions to the other end then
We have a mode of a queue that is we can insert an item at the rear end and remove an item at the front
end obeying the discipline first in first out. If we restrict the insertions and deletions to occur only at one
end of list the beginning then the model is called stacks. Stacks are all inherently one-dimensional. A tree
represents a two dimension linked list. Trees are frequently encounters in everyday life one example are
organization chart and the other is sports tournament chart.
A doubly-linked list whose nodes contain three fields: an integer value, the link forward to the next node,
and the link backward to the previous node
Inserting elements:
Inserting the element at specify the position.
1. If position is Head next of the new element is head and Head is know new element.
2. If position is middle of the list next of list is new element and next of new element is list.
p D N P D
P D N
P D N P D
P D N
void insert( )
{
void after( ); void before( );
int ch;
printf("\n Inserting a node:");
printf("\n 1. Insert after a node.");
printf("\n 2. Insert before a node.");
printf("\n choice :");
scanf("%d",&ch);
switch (ch)
{ case 1 : after( ); break;
case 2 : before( ); break;
default : printf("\n Double Linked List Implementation");
getch( );
}
}
void after( )
{
struct node *t,*p; int i,pos;
t=(struct node *) malloc(sizeof(struct node));
printf("\n total no of nodes are in list %d\n",count);
printf("\n enter the position to insert");
scanf("%d",&pos);
tpre=NULL;
printf("\n enter any no:");
scanf("%d",&tdata);
t next =NULL;
if(pos= =count)
{ tailnext=t;
tpre=tail;
tail=t;
}
else
{ p=head;
for(i=1;i<pos;i++)
p=p next;
t next =p next; p next pre=t;
p next =t; tpre=p;
}
count++;
}
void before( )
{
struct node *t,*p,*q;
int i,pos;
t=(struct node *) malloc(sizeof(struct node));
printf("\n total no of nodes are in list %d\n",count);
printf("\n enter the position to insert");
scanf("%d",&pos);
tpre=NULL;
printf("\n enter any no:");
scanf("%d",&tdata);
t next =NULL;
p=head;
if(pos = =1)
{ tnext=p;
ppre=t;
head=t;
}
else
{ for(i=1;i<pos-1;i++)
p=p next;
t next =p next; p next pre=t;
p next =t; tpre=p;
}
count++;
}
Deleting element
Similarly, we have functions for removing the node after a given node, and for removing a node from the
beginning of the list. The diagram demonstrates the former. To find and remove a particular node, one
must again keep track of the previous element.
P d n
P d n
P d n
In the above figure the address of first node is connected to next node
void del( )
{ struct node *p,*q; int pos,i,t;
printf("\ntotal no of nodes in list %d\n",count);
if(count = =0)
printf(“\n Empty D.L.L.”);
else
{ printf("\n enter the position to delete"); scanf("%d",&pos);
p=head;
if(pos = =1)
{ q=p next;
p next=NULL; qpre=NULL;
head=q; free(p);
}
else
{ for(i=1;i<pos-1;i++)
p=p next;
q=p next;
if(pos = =count)
{
qpre=NULL; p next =NULL;
tail=p; free(q);
}
else
{ p next =q next; q next pre=p;
qpre=q next = NULL; free(q);
}
}
count--;
}
}
Write a C program that uses functions to performing following operations on doubly linked list:
i) Creation ii) Insertion iii) Deletion iv) Traversal in both ways
______________________________________________________________________
#include<stdio.h>
#include<alloc.h>
#include<conio.h>
struct node
{ struct node *pre;
int data;
struct node * next;
};
struct node *head,*tail;
int count=0;
void main( )
{ void display( ); void insert( );
void add( ); void del( );
int opt;
head=tail=NULL;
while(1)
{ clrscr( );
printf(" 1.add.");
printf("\n 2.display.");
printf("\n 3.insert.");
printf("\n 4.del.");
printf("\n 5.exit.");
printf("\n \n choice:");
scanf("%d",&opt);
switch(opt)
{
case 1 : add( ); break;
case 2 : display( ); break;
case 3 : insert( ); break;
case 4 : del( ); break;
case 5 : exit( );
default : printf("\n Double Linked List Implementation");
getch( );
}
}
}
void add( )
{
struct node *temp;
temp=(struct node *) malloc(sizeof(struct node));
printf("\ntotal no of nodes are in list %d\n",count);
temppre=NULL;
printf("\n enter any no:");
scanf("%d",&tempdata);
tempnext=NULL;
if(head = = NULL)
head=tail=temp;
else
{ tail next =temp;
temppre=tail;
tail=temp;
}
count++;
}
void display( )
{ struct node *t;
printf("\n total no of nodes are in list %d\n",count);
if(count = = 0)
printf(“Empty D.L.L.”);
else
{ t=head;
while(t)
{ printf("%d ",tdata);
t=t next;
}
t=tail;
while(t)
{ printf("%d ",tdata);
t=t pre;
}
}
getch( );
}
void insert( )
{
void after( ); void before( );
int ch;
printf("\n Inserting a node:");
printf("\n 1. Insert after a node.");
printf("\n 2. Insert before a node.");
printf("\n choice :");
scanf("%d",&ch);
switch(ch)
{ case 1 : after( ); break;
case 2 : before( ); break;
default : printf("\n Double Linked List Implementation");
getch( );
}
}
void after( )
{
struct node *t,*p; int i,pos;
t=(struct node *) malloc(sizeof(struct node));
printf("\n total no of nodes are in list %d\n",count);
printf("\n enter the position to insert");
scanf("%d",&pos);
tpre=NULL;
printf("\n enter any no:");
scanf("%d",&tdata);
t next =NULL;
if(pos= =count)
{ tailnext=t;
tpre=tail;
tail=t;
}
else
{ p=head;
for(i=1;i<pos;i++)
p=p next;
t next =p next;
p next pre=t;
p next =t;
tpre=p;
}
count++;
}
void before( )
{
struct node *t,*p,*q; int i,pos;
t=(struct node *) malloc(sizeof(struct node));
printf("\n total no of nodes are in list %d\n",count);
printf("\n enter the position to insert");
scanf("%d",&pos);
tpre=NULL;
printf("\n enter any no:");
scanf("%d",&tdata);
t next =NULL;
p=head;
if(pos = =1)
{ tnext=p;
ppre=t;
head=t;
}
else
{ for(i=1;i<pos-1;i++)
p=p next;
t next =p next;
p next pre=t;
p next =t;
tpre=p;
}
count++;
}
void del( )
{ struct node *p,*q;
int pos,i,t;
printf("\ntotal no of nodes in list %d\n",count);
if(count = =0)
printf(“\n Empty D.L.L.”);
else
{ printf("\n enter the position to delete");
scanf("%d",&pos);
p=head;
if(pos = =1)
{ q=p next;
p next=NULL;
qpre=NULL;
head=q;
free(p);
}
else
{ for(i=1;i<pos-1;i++)
p=p next;
q=p next;
if(pos = =count)
{
qpre=NULL; p next =NULL;
tail=p; free(q);
}
else
{ p next =q next; q next pre=p;
qpre=q next = NULL; free(q);
}
}
count--;
}
}
INPUT:
1. add
2. display
3. insert
4. delete
5. exit
Choice: 1
OUTPUT:
total no of nodes are in list 0
enter any no: 10
8.4 Circularly-linked list
In a circularly linked list, all nodes are linked in a continuous circle, without using null. For lists with a front
and a back (such as a queue), one stores a reference to the last node in the list. The next node after the
last node is the first node. Elements can be added to the back of the list and removed from the front in
constant time.
Circularly-linked lists can be either singly or doubly linked.
Both types of circularly-linked lists benefit from the ability to traverse the full list beginning at any given
node. This often allows us to avoid storing first Node and last Node, although if the list may be empty we
need a special representation for the empty list, such as a last Node variable which points to some node
in the list or is null if it's empty; we use such a last Node here. This representation significantly simplifies
adding and removing nodes with a non-empty list, but empty lists are then a special case.
The circular linked list is represented as follows:
void after( )
{
struct node *t,*p;
int i,pos;
t=(struct node *) malloc(sizeof(struct node));
printf("\n total no of nodes are in list %d\n",count);
printf("\n enter the position to insert");
scanf("%d",&pos);
printf("\n enter any no:");
scanf("%d",&t->data);
t->next=NULL;
if(pos == count)
{
tail->next=t;
tail=t;
tail->next=head;
}
else
{
p=head;
for(i=1;i<pos;i++)
p=p->next;
t->next=p->next;
p->next=t;
}
count++;
}
void before( )
{
struct node *t,*p,*q;
int i,pos;
t=(struct node *) malloc(sizeof(struct node));
printf("\ntotal no of nodes are in list %d\n",count);
printf("\nenter the position to insert");
scanf("%d",&pos);
printf("\nenter any no:");
scanf("%d",&t->data);
t->next=NULL;
p=head;
if(pos == 1)
{
t->next=p;
head=t;
tail->next=head;
}
else
{ for(i=1;i<pos-1;i++)
p=p->next;
q=p->next;
t-> next =q;
p-> next =t;
}
count++;
}
void del( )
{
struct node *p,*q;
int pos,i;
printf("\n total no of nodes are in list %d\n",count);
if(count == 0)
printf("\n Empty C.L.L.");
else
{
printf("\n enter the position to insert");
scanf("%d",&pos);
p=head;
if(pos == 1)
{
q=p-> next;
p-> next = NULL;
head=q;
free(p);
tail->next=head;
}
else
{
for(i=1;i<pos-1;i++)
p=p-> next;
q=p-> next;
if(pos == count)
{
p-> next =NULL;
tail=p;
free(q);
tail->next=head;
}
else
{
p-> next =q-> next;
q-> next =NULL;
free(q);
}
}
count--;
}
____________________________________________________________________________________
INPUT:
1. add
2. display
3. insert
4. delete
5. exit
choice :1
OUTPUT:
total no of nodes are in list 0
enter any no: 10
8.5 Stacks
A Stack is linear data structure it performs both insertion and deletion at one end , A stack is called (LIFO)
i.e. last in first out because the element which is inserted first into the stack that element comes out last.
The example of the stack is books in the rack.
1. Push ()
2. Pop ()
3. Peep ()
Stack
Now, let's perform Push (stack, A), giving:
|
<-- top
Stack
Again, another push operation, Push (stack, B), giving:
<-- top
Stack
Conditions for push operation?
2.
----------------- -----
A B |1|
----------------- -----
0 1 2 3 top
Contents
-----
| B | <-- top
-----
|A|
-----
Stack
Now let's remove an item, letter = Pop (stack), giving:
----- -----
| A | <-- top | B |
----- -----
Stack letter
else
{
printf (“enter element :”);
scanf(“%d”,&x);
item[ ++top]=x;
}
}
void pop( )
{
int x;
if(top = = -1)
printf(“\n stack is under flow”);
else
{
x = item[ top--];
printf(“\n deleted element :%d”,x);
}
getch( );
}
void peep( )
{
int i;
if(top = = -1)
printf(“\n stack is empty”);
else
{
for(i=0;i<=top;i++)
printf(“%d\t”, item[i]);
}
getch( );
}
OUTPUT:
1. push
2. pop
3. peep
4. exit
Choice: 1
enter element: 10
top
Using a linked list is one way to implement a stack so that it can handle essentially any number of
elements.
Push (): operation both initializes an empty stack, and adds a new node to a non-empty one. It works by
receiving a data value to push onto the stack, along with a target stack, creating a new node by allocating
memory for it, and then inserting it into a linked list as the new head
Here is what a linked list implementing a stack with 3 elements might look like:
A B C
top
Where should we consider the top of the stack to be, the beginning or end of the list
Pop (): operation removes the head from the linked list, and assigns the pointer to the head to the
previous second node. It check whether the list is empty before popping from it:
A B
top
/* Implementation of Stack using Linked List*/
_____________________________________________________________________________
#include<stdio.h>
#include<conio.h>
#include<alloc.h>
struct node
{
int data;
struct node *next;
};
struct node *head,*tail;
int count=0;
void main( )
{
void push( );
void pop( );
void peep( );
int ch;
head=tail=NULL;
while(1)
{
clrscr( );
printf("1. push");
printf("\n2. pop");
printf("\n3. peep");
printf("\n4. exit");
printf("\n choice :");
scanf("%d",&ch);
switch(ch)
{
case 1 : push( ); break;
case 2 : pop( ); break;
case 3 : peep( ); break;
case 4 : exit( );
default : printf("\n Stack using L.L "); getch( );
}
}
}
void push( )
{ struct node *temp;
temp=(struct node *) malloc(sizeof(struct node));
printf("enter any no :");
scanf("%d",&tempdata);
tempnext=NULL;
if(head = = NULL)
head=tail=temp;
else
{ tailnext=temp;
tail=temp;
}
count++;
}
void pop( )
{ struct node *p,*q;
int i;
if(count = = 0)
{ printf("\n stack under flow");
getch( );
}
else
{ p=head;
if(count = = 1)
{
free(p); head = tail = NULL;
}
else
{ for(i=1;i<count-1;i++)
p=pnext;
q=pnext;
pnext=NULL;
free(q); tail=p;
}
count--;
}
}
void peep( )
{
int i;
struct node *p;
if(count= = 0)
printf(“\n stack is empty”);
else
{ p=head;
while(p)
{
printf("%d\t",pdata);
p=pnext;
}
}
getch( );
}
_____________________________________________________________________________
OUTPUT:
1. push
2. pop
3. peep
4. exit
choice :1
enter element :1
Stack application:
Applications of stack are performed mathematically those classified into as follow
1. Infix
2. Prefix
3. Postfix
Infix notation
In this notation operators are placed between operands in expression
Example: A+B*C/D
Prefix notation
In this notation operators are placed before the operands in expression.
Example: +A/*BCD
Postfix notation
In this notation operators are placed after the operands in expression.
Example: BC*D/A+
In normal algebra we use the infix notation like a+b*c. The corresponding postfix notation is abc*+. The
algorithm for the conversion is as follows:
Scan the Infix string from left to right.
Initialize an empty stack.
If the scanned character is an operand, add it to the Postfix string. If the scanned character is an
operator and if the stack is empty Push the character to stack.
If the scanned character is an Operand and the stack is not empty, compare the
precedence of the character with the element on top of the stack (topStack). If top Stack
has higher precedence over the scanned character Pop the stack else Push the scanned
character to stack. Repeat this step as long as stack is not empty and top Stack has
precedence over the character.
Repeat this step till all the characters are scanned.
(After all characters are scanned, we have to add any character that the stack may have to the
Postfix string.) If stack is not empty add topStack to Postfix string and Pop the stack. Repeat this
step as long as stack is not empty.
Return the Postfix string.
Example :
Let us see how the above algorithm will be implemented using an example.
Initially the Stack is empty and our Postfix string has no characters. Now, the first character scanned is 'a'.
'a' is added to the Postfix string. The next character scanned is '+'. It being an operator, it is pushed to the
stack.
Postfix String
Stack
Next character scanned is 'b' which will be placed in the Postfix string. Next character is '*' which is an
operator. Now, the top element of the stack is '+' which has lower precedence than '*', so '*' will be pushed
to the stack.
Postfix String
Stack
The next character is 'c' which is placed in the Postfix string. Next character scanned is '-'. The topmost
character in the stack is '*' which has a higher precedence than '-'. Thus '*' will be popped out from the
stack and added to the Postfix string. Even now the stack is not empty. Now the topmost element of the
stack is '+' which has equal priority to '-'. So pop the '+' from the stack and add it to the Postfix string. The
'-' will be pushed to the stack.
Postfix String
Stack
Next character is 'd' which is added to Postfix string. Now all characters have been scanned so we must
pop the remaining elements from the stack and add it to the Postfix string. At this stage we have only a '-'
in the stack. It is popped out and added to the Postfix string. So, after all characters are scanned, this is
how the stack and Postfix string will be :
Postfix String
Stack
End result :
• Infix String : a+b*c-d
• Postfix String : abc*+d-
while( !empty(&s) )
x[i++]=pop(&s);
x[i]='\0';
printf("\n the postfix expression is %s",x);
getch( );
}
int pred(char x,char p)
{ if(x= ='$' && (p= ='/' || p= ='*' || p= ='+' || p= ='-') )
return(1);
else if((x= ='/' || x = =’*’) && (p = = ‘/’ || p= ='*' || p= ='+' || p= ='-'))
return(1);
else if(x= ='*' && (p= ='+' || p= ='-'))
return(1);
else if((x= ='+' || x = = ‘-‘)&& p= ='-' )
return(1);
else
return(0);
}
void push( struct stack *s,char c)
{ if(stop>=max-1)
{ printf("stack is overflow\n"); exit( );
}
else
sitem[++(stop)]=c;
}
char pop(struct stack *s)
{ if(stop = = -1 )
{ printf("\nstack is underflow "); exit( );
}
else
return(sitem[(stop)--]);
}
int empty(struct stack *s)
{ if(stop = = -1)
return(1);
else
return(0);
}
____________________________________________________________________________
OUTPUT:
enter the infix expression : a+b
the postfix expression is ab+
Postfix Expression:
In normal algebra we use the infix notation like a+b*c. The corresponding postfix notation is abc*+. The
algorithm for the conversion is as follows:
Scan the Postfix string from left to right.
Initialize an empty stack.
If the scanned character is an operand, add it to the stack. If the scanned character is an
operator, there will be atleast two operands in the stack.
If the scanned character is an Operator, then we store the top most element of the
stack (top Stack) in a variable temp. Pop the stack. Now evaluate top
Stack(Operator)temp. Let the result of this operation be retVal. Pop the stack and Push
retVal into the stack.
Repeat this step till all the characters are scanned.
After all characters are scanned, we will have only one element in the stack. Return topStack.
Example :
Let us see how the above algorithm will be imlemented using an example.
Initially the Stack is empty. Now, the first three characters scanned are 1,2 and 3, which are operands.
Thus they will be pushed into the stack in that order.
Expression
Stack
Next character scanned is "*", which is an operator. Thus, we pop the top two elements from the stack
and perform the "*" operation with the two operands. The second operand will be the first element that is
popped.
Expression
Stack
The value of the expression (2*3) that has been evaluated (6) is pushed into the stack.
Expression
Stack
Next character scanned is "+", which is an operator. Thus, we pop the top two elements from the stack
and perform the "+" operation with the two operands. The second operand will be the first element that is
popped.
Expression
Stack
The value of the expression(1+6) that has been evaluated(7) is pushed into the stack.
Expression
Stack
Expression
Stack
Next character scanned is "-", which is an operator. Thus, we pop the top two elements from the stack
and perform the "-" operation with the two operands. The second operand will be the first element that is
popped.
Evaluating postfix expression
_____________________________________________________________________________
#include<ctype.h>
#include<math.h>
#define max 20
struct stack
{ int top;
int item[max];
};
void main( )
{
void push(struct stack *s,int x);
int pop(struct stack *s);
struct stack s;
int op1,op2,i;
char c;
clrscr( );
s.top=-1;
printf("enter postfix expression :");
while( (c=getchar( )) !=EOF)
{
if( isdigit(c) )
push(&s,c-'0');
else
{ op2=pop(&s);
op1=pop(&s);
switch(c)
{
case '+' : push(&s,op1+op2); break;
case '-' : push(&s,op1-op2); break;
case '*' : push(&s,op1*op2); break;
case '/' : push(&s,op1/op2); break;
case '$' : push(&s,pow(op1,op2)); break;
default : printf("\n postfix evaluation"); getch( );
}
}
}
_____________________________________________________________________________
OUTPUT:
enter postfix expression : 12+
the resultant value is 3
Queues
Queue is similarly to the stacks , it’s also linear data structures in which data can be inserted only one end
,called the rear, and the deleting the element from the other end called the front, it’s also called FIFO, i.e
first in- first out.
The queue is another data structure. A physical analogy for a queue is a line at a bank. When you go to the bank,
customers go to the rear (end) of the line and customers come off of the line (i.e., are serviced) from the front of the
line.
Aside: In fact, other English-speaking countries use this term for a line, e.g., they might say "Queue up!" rather than
"Get in a line!"
Like a stack, a queue usually holds things of the same type. We usually draw queues horizontally. Here's a queue of
characters with 3 elements:
queue
-------------
|a|b|c|
-------------
^ ^
| |
front rear
The main property of a queue is that objects go on the rear and come off of the front of the queue.
Here are the minimal set of operations we'd need for an abstract queue:
Operations of queue are as follow
1. push()
2. pop ()
3.peep() (Display)
Push (): push is nothing but inserting the element into queue
Implementing a queue with an array:
Queues are useful because they produce a certain order in which the contents of the queue are used. Let's see what
order that is by looking at a queue of characters. Now, what would a particular sequence of Enter and Deletes do to
this queue:
queue
-------------
|a|b|c|
-------------
^ ^
| |
front rear
Now, Enter(queue, 'd')...
queue
-----------------
|a|b|c|d|
-----------------
^ ^
| |
front rear
Since a queue usually holds a bunch of items with the same type, we could implement a queue with an array. Let's
simplify our array implementation of a queue by using an array of a fixed size, MAX_QUEUE_SIZE.
Conditions for push operation?
Pop (): Pop is nothing but deleting the element from stack.
Conditions for pop operation?
queue ch
------------- -----
|b|c|d| |a|
------------- -----
^ ^
| |
front rear
You'll notice that the queue enforces a certain order to the use of its contents. Is the ordering of the queue Last thing
In is the First thing Out (LIFO) or First Thing In is the First thing Out (FIFO)?
queue
-----------------
|a|b|c|d|
-----------------
^ ^
| |
front rear
_____________________________________________________________________________
#define max 10
int item[max];
int front = -1, rear=-1;
void main( )
{ void push( );
void pop( );
void peep( );
int n;
while(1)
{ clrscr( );
printf(“\n 1. push”);
printf(“\n 2. pop”);
printf(“\n 3. peep”);
printf(“\n 4. exit”);
printf(“\n choice :”);
scanf(“%d”,&n);
switch(n)
{
case 1: push( ); break;
case 2: pop( ); break;
case 3: peep( ); break;
case 4: exit( );
default : printf(“\n queue implementation”); getch( );
}
}
}
void push( )
{
int x;
if(rear = = max-1)
{
printf(“\n queue is over flow”);
getch( );
}
else
{
printf (“enter element :”);
scanf(“%d”,&x);
item[ ++rear]=x;
}
}
void pop( )
{
int x;
if(front = = rear)
printf(“\n queue is under flow”);
else
{
x = item[ ++front];
printf(“\n deleted element :%d”,x);
}
getch( );
}
void peep( )
{
int i;
if(front = = rear)
printf(“\n queue is empty”);
else
{
for(i=front +1; i<=rear ; i++)
printf(“%d\t”, item[i]);
}
getch( );
}
OUTPUT:
1. push
2. pop
3. peep
4. exit
choice : 1
enter element: 1
Implementing a queue with a linked list:
Using a linked list is one way to implement a queue so that it can handle essentially any number of
elements.
Here is what a linked list implementing a queue with 3 elements might look like:
list
|
v
-------- -------- ---------
| A | <-+--| B | <-+--| C |
-------- -------- ---------
^ ^
| |
front rear
void push( )
{
struct node *temp;
temp=(struct node *) malloc(sizeof(struct node));
printf("enter any no :");
scanf("%d",&tempdata);
tempnext=NULL;
if(head = = NULL)
head=tail=temp;
else
{ tailnext=temp;
tail=temp;
}
count++;
}
void pop( )
{
struct node *p;
if(count = = 0)
{
printf("queue under flow");
getch( );
}
else
{ p=head;
if(count = = 1)
{
free(p);
head = tail = NULL;
}
else
{
head=pnext; pnext=NULL;
free(p); count--;
}
}
}
void peep( )
{
int i;
struct node *p;
if(count = = 0)
printf(“\n queue is empty”);
else
{
p=head;
while(p)
{
printf("%d\t",pdata);
p=pnext;
}
}
getch( );
}
_____________________________________________________________________________
OUTPUT:
1. push
2. pop
3. peep
4. exit
choice: 1
enter element: 1
Programming Exercise:
Multiple choices:
Q.1 Is a linked list a linear or non-linear data structure?
(a) Linear (b) Non-linear (c) Can’t say
(d) None
Review Questions: