Data Structures 8.

1 Introduction to Data Structures
A data structure is a group of items (data) organized in many different ways (logical or mathematical), in which each item is identified by it's own identifier. Each of the data is known as a member of the data structure. Most often we face situations in programming where data is dynamic in nature that is the number of data items keep changing during the execution of the program. For example, consider the program for processing the list of customers of a company. The list grows when new customer names are added and shrinks when names are deleted. When the list grows it needs more memory space to be allocated to accommodate the additional data. In the reverse case the memory space is to be deleted. This type of situation can be handled more efficiently using data structure in conjunction with dynamic memory management techniques. Data structures provide flexibility in adding, deleting or rearranging data items at run time. Dynamic memory management technique permits us to allocate additional memory space or to release unwanted space at run time. In other words data structure is a collection of data elements whose organization is characterized by assessing operations that are used to store and retrieve the individual data elements, the implementation of the composite data members in an abstract data type. An abstract data type can be defined as a data type whose properties are specified independently of any particular implementation.

The data structures are classified in the following categories:• Linear data structures • Nonlinear data structures

Data structure

Linear

Nonlinear

A Array

Stacks

Queue s

Trees

Graph s

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 builtin 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

A list is a set of items organized sequentially. An array is an example of a list. In an array , the sequential organization of data is provided implicitly by it's index. We use array index for accessing or manipulating array elements. The dis-advantage of using an array to store data elements is that the size of the array is pre-defined. A programmer does not have any control on defining the size of the array at run time. To overcome this problem, 'C' provides the concept of linked lists.

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 To create a linked list, following steps are required :1. Declare a structure that defines the list elements. 2. Within the structure body declare the variable(s) of each node that will contain information and the pointer of each node. 3. Declare the external pointer and the node(s) of that structure type. A node may contain any number of information fields. 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

After create the elements we can add the elements as follow If head is created then we can add the element to tail otherwise then is’t a head

Data

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",&tempdata); tempnext=NULL; if(head = = NULL) head=tail=temp; else { tailnext=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

New

Data

Data Next

Data
New

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",&tdata); tnext=NULL; if(pos = = count) { tailnext=t; tail=t; }

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; } else { for(i=1;i<pos-1;i++) p=pnext; q=pnext; 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",&tempdata); tempnext=NULL;

if(head = = NULL) head=tail=temp; else { tailnext=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 ",tdata); t=tnext; } } 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",&tdata); tnext=NULL; if(pos = = count) { tailnext=t; tail=t; } 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; } 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 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); }

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

else {

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.

In a doubly-linked list, each node contains, besides the next-node link, a second link field pointing to the previous node in the sequence. The two links may be called forward(s) and backwards. In double linked list node is divided into three parts 1. Data, 2. Address of previous node 3. Address of next node

Previo us

Data

Next

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

Function for inserting elements at specified position 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); tpre=NULL; printf("\n enter any no:"); scanf("%d",&tdata); t next =NULL; if(pos= =count) { tailnext=t; tpre=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; } count++; }

tpre=p;

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); tpre=NULL; printf("\n enter any no:"); scanf("%d",&tdata); t next =NULL; p=head; if(pos = =1) { tnext=p; ppre=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; tpre=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

Function for deleting elements at specified position 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; qpre=NULL; head=q; free(p); } else {

for(i=1;i<pos-1;i++) p=p next; q=p next; if(pos = =count) { qpre=NULL; p next =NULL; tail=p; free(q); } else { p next =q next; q next pre=p; qpre=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); temppre=NULL; printf("\n enter any no:"); scanf("%d",&tempdata); tempnext=NULL; if(head = = NULL)

head=tail=temp; else { tail next =temp; temppre=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 ",tdata); t=t next; } t=tail; while(t) { printf("%d ",tdata); 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); tpre=NULL; printf("\n enter any no:"); scanf("%d",&tdata); t next =NULL; if(pos= =count) { tailnext=t; tpre=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; tpre=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); tpre=NULL; printf("\n enter any no:"); scanf("%d",&tdata); t next =NULL; p=head; if(pos = =1) { tnext=p; ppre=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; tpre=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; qpre=NULL; head=q; free(p); } else { for(i=1;i<pos-1;i++) p=p next; q=p next; if(pos = =count) { qpre=NULL; p next =NULL; tail=p; free(q); } else { p next =q next; q next pre=p; qpre=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

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:

/* Implementation of circular Linked List */
____________________________________________________________________________________ #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 C.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",&temp->data); temp->next=NULL; if(head = = NULL) head=tail=temp; else { tail->next=temp; tail=temp; tail->next=head; } count++; } void display( ) { int i; 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; for(i=1;i<=count;i++) { printf("%d ",t->data); t=t->next; } } 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 C.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",&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. Every operation of the stack is performs top of the stack. Operations of the stack are as follow 1. Push () 2. Pop () 3. Peep ()

Push ( ): push is nothing but inserting the element into stack
Sequences of Push do to this stack? We begin with stack empty:

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? 1. Check stack is full or not? I.e. top=Max 2. Otherwise insert the element into the stack

Implementing a stack with an array:
Since a stack usually holds a bunch of items with the same type, we could implement a stack as an array. Consider how we could have an array of characters, contents, to hold the contents of the stack, and an integer top that holds the index of the element at the top of the stack. We choose the array to be of size 4 for now. Starting with an empty stack, we have: --------------------| -1| ----------------- ----0 1 2 3 top Contents Now, the same sequence of operations we used before, namely: 1. Push (stack, 'A') 2. Push (stack, 'B') Produce the following effects: 1. ----------------A ----------------0 1 2 3 Contents ----|0| ----top

2. ----------------- ----A B |1| ----------------- ----0 1 2 3 top

Contents

Implementation of push () operation
_____________________________________________________________________________ void push( ) { int x; if(top = = max-1) { printf(“\n stack is over flow”); getch( ); } else { printf (“enter element :”); scanf(“%d”,&x); item[ ++top]=x; } }

Pop () : Pop is nothing but deleting the element from stack.
Conditions for pop operation? 1. Check stack is empty or not? I.e. top=-1 2. Otherwise delete the element from the stack Now the stack is as follow ----| B | <-- top ----|A| ----Stack Now let's remove an item, letter = Pop (stack), giving: --------| A | <-- top | B | --------Stack letter

Implementation of pop () operation
_____________________________________________________________________________ Void pop( ) { int x; if(top = = -1) printf(“\n stack is under flow”); else

{ x = item[ top--]; printf(“\n deleted element :%d”,x); } getch( ); }

________________________________________________________________ Peep (): Peep is nothing but display the elements in queue
Condition for peep operation? 1. Check queue is empty or not? I.e. top=-1 2. Otherwise display the element in the stack

Implementation of peep () operation
_____________________________________________________________________________ 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( ); }

Write a C program that implement stack (its operations) using Arrays ______________________________________________________________________ #define max 10 int top; int item[max]; void main( ) { void push( ); void pop( ); void peep( ); int n; top=-1; 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 stack implementation”); getch( ); } } } void push( ) { int x; if(top = = max-1) { printf(“\n stack is over flow”); getch( ); }

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

Implementing a stack with a linked list:
The linked-list implementation is equally simple and straightforward. In fact, a stack linked-list is much simpler than most linked-list implementations: it requires that we implement a linked-list where only the head node or element can be removed, or popped, and a node can only be inserted by becoming the new head node. Unlike the array implementation, our structure typedef corresponds not to the entire stack structure, but to a single node: typedef struct stack { int data; struct stack *next; } stack

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",&tempdata); tempnext=NULL;

if(head = = NULL) head=tail=temp; else { tailnext=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=pnext; q=pnext; pnext=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",pdata); p=pnext; } } 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+

Infix to Postfix Conversion:
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. Infix String: a+b*c-d 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-

Write a C program that uses Stack operations to perform the following: i) Converting infix expression into postfix expression _______________________________________________________________________ #include<stdio.h> #include<ctype.h> #define max 20 struct stack { int top; char item[max]; }; void main( ) { int pred(char x,char p); void push( struct stack *s,char c); char pop(struct stack *s); int empty(struct stack *s); struct stack s; char c,x[50]; int i=0; clrscr( ); s.top=-1; printf("enter the infix expression :"); while( (c=getchar( ))!='\n') { if( isalnum(c) ) x[i++]=c; else if( c= ='\$' || c= ='/' || c= ='*' || c= ='+' || c= ='-' || c= ='(' ) { while(!empty(&s) && pred(s.item[s.top],c) ) x[i++]=pop(&s); push(&s,c); } else if( c==')' ) { while( s.item[s.top]!= '(' ) x[i++]=pop(&s); pop(&s); }

} while( !empty(&s) ) x[i++]=pop(&s); x[i]='###BOT_TEXT###'; 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(stop>=max-1) { printf("stack is overflow\n"); exit( ); } else sitem[++(stop)]=c; } char pop(struct stack *s) { if(stop = = -1 ) { printf("\nstack is underflow "); exit( ); } else return(sitem[(stop)--]); } int empty(struct stack *s) { if(stop = = -1) return(1); else return(0); } ____________________________________________________________________________ OUTPUT: enter the infix expression : a+b the postfix expression is ab+

Postfix Expression:
The Postfix(Post order) form of the above expression is "23*45/-".

Postfix Evaluation: 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. Postfix String : 123*+4Initially 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 Next character scanned is "4", which is added to 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.

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( ); } } }

printf("the resultant value is %d",pop(&s)); getch( ); } void push(struct stack *s,int x) { if(stop= =max-1) {

printf("stack is overflow"); getch( ); exit( ); } else { sitem[++stop]=x; } } int pop(struct stack *s) { if(stop = = -1) { printf("stack is underflow"); getch( ); exit( ); } else { return(sitem[(stop)--]); } } _____________________________________________________________________________ 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? 1. Check queue is full or not? I.e. rear=max-1. 2. Otherwise insert the element into the queue.

Implementation of push () operation
_____________________________________________________________________________ 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; } }

_______________________________________________________

Pop (): Pop is nothing but deleting the element from stack.

Conditions for pop operation? 1. Check queue is empty or not? I.e. front=rear 2. Otherwise delete the element from the queue
Implementing a queue with an array: queue ----------------|a|b|c|d| ----------------^ ^ | | front rear Now, ch = Delete (queue)...

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)?

Implementation of pop () operation
_____________________________________________________________________________ void pop( ) { int x; if(front = = rear) printf(“\n queue is under flow”); else { x = item[ ++front]; printf(“\n deleted element :%d”,x); } getch( ); }

Peep(): Peep is nothing but display the elements in queue
Condition for peep operation? 1. Check queue is empty or not? I.e. front=rear

2. Otherwise display the element in the queue
queue ----------------|a|b|c|d| ----------------^ ^ | | front rear

Implementation of peep() operation
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( ); } _____________________________________________________________________________

Write a C program that implement queue (its operations) using arrays? #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

/* Implementation Queue 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 CHIOCE:"); scanf("%d",&ch); switch(ch) { case 1 : push( ); break;

case 2 : pop( ); break; case 3 : peep( ); break; case 4 : exit( ); default : printf("\n Queue using L.L."); getch( ); } } }

void push( ) { struct node *temp; temp=(struct node *) malloc(sizeof(struct node)); printf("enter any no :"); scanf("%d",&tempdata); tempnext=NULL; if(head = = NULL) head=tail=temp; else { tailnext=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=pnext; pnext=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",pdata); p=pnext; } } getch( ); } _____________________________________________________________________________ OUTPUT: 1. push 2. pop 3. peep 4. exit choice: 1 enter element: 1

Programming Exercise: 1. Write a non-recursive simulation of towers of Hanoi. 2. Write recursive function for towers of Hanoi. 3. Program to convert Prefix to postfix using stacks. 4. Program to convert postfix expression to prefix expression. 5. Write a program to evaluate postfix expression 6. Program to evaluate prefix expression. 7 .Write a program to implement de queues 8 Program to implement priority queues. 9. Program to check whether a given string is palindrome or not using stacks. 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 Q.2 How can I search for data in a linked list? (a) Non-linear search (b) Linear search (c) Can’t say (d) None Q.3 What is each entry in a linked list called?