Linked Representations of Stacks - Queues
Linked Representations of Stacks - Queues
Several data structures can be used to implement a stack. Here we implement a stack as a linked
list.
Data structure:
To implement linked list stack, we need two different structures,
o Head node
o Data node
The head structure contains metadata that is, data about data – and a pointer to the top of the
stack.
The data structure contains data and a link pointer to the next node in the stack.
The conceptual and physical implementations of the stack are shown in fig.
Stack algorithms:
The eight stack operations discussed in this section should be sufficient to solve any basic stack
problem.
If any additional operations are required we could easily add.
Implementation of stack depends on implementation language, it is usually implemented with a
stack head structure in C
The below figure show the four most common stack operations are: create stack, push stack,
pop stack, destroy stack.
Operations such as stack top are not shown in the figure because they do not change the stack
structure.
a. Create stack:
Create stack allocates memory for the stack structure and initializes its metadata(a data about
data).
The pseudo code is shown in algorithm
Create stack algorithm:
Algorithm createstack
Creates and initializes metadata structure
Pre Nothing
Post structure created and initialized
Return Stack head
1. Allocate memory for stack head
2. Set count to 0
3. Set top to NULL
4. Return stack head
end create stack
b. Push Stack:
Push stack inserts an element into the stack
The first thing we need to do when we push data into a stack is find memory for the node.
We must therefore allocate a node from dynamic memory
Once the memory is allocated, we simply assign the data to the stack node and then set the link
pointer to point to the node currently indicated as the stack top.
We also need to update the stack top pointer and add 1 to the stack count field
Figure traces a push a stack operation in which a new pointer (PNew) is used to identify the data
to be inserted into the stack.
To develop the insertion algorithm using a linked list, we need to analyze three different stack
conditions:
1. Insertion into an empty stack
2. Insertion into a stack with data, and
3. Insertion into a stack when the available memory is exhausted
The third is an error condition
When we insert into a stack that contains data,
The new nodes link pointer is set to point to the node currently at the top , and
The stack’s top pointer is set to point to the new node.
Push stack design: Algorithm
Algorithm pushstack (stack,data)
Insert(push) one item into the stack
Pre stack passed by reference
Data contain data to be pushed into stack
Post data have been pushed into stack
1. Allocate new node
2. Store data in new node
3. Make current top node the second node
4. Make new node the top
5. Increment stack count
end pushstack
c. Pop stack:
Pop stack sends the data in the node at the top of stack back to the calling algorithm
It then adjusts the pointers to logically delete the node, it is physically deleted by recycling the
memory, that is returning it to dynamic memory.
After count is adjusted by subtracting 1, the algorithm returns the status to the caller, if the top
was successful, it returns true; if the stack is empty when pop is called, it returns false.
The operations for pop stack are traced in figure.
d. Stack top
The stack top algorithms send the data at the top of stack back to the calling module without
deleting the top node.
This is included in case the application needs to know what will be deleted with the next pop
stack
Algorithm: stack top pseudo code
Algorithm stackTop (stack,dataout)
This algorithm retrieves the data from the top of the stack without changing the stack
Pre stack is metadata structure to a valid stack
datout reference variable to receive data
Post Data have been returned to calling algorithm
Return true if data returned, false if underflow
1. if(stack empty)
1. Set success to false
2. else
1. Set dataout to data in top node
2. Set success to true
3. endif
4. return success
end stack Top
e. Empty stack
Empty stack is provided to implement the structured programming concept of data hiding: if the
entire program has access to the stack head structure, it is not needed.
If the stack is implemented as a separately compiled program to be linked with other programs,
the calling program may not have access to the stack head node.
In these cases it is necessary to provide a way to determine whether the stack is empty.
The pseudo code for empty stack is shown in algorithm
Algorithm: Empty stack
Algorithm emptystack (stack)
Determines if stack is empty and returns a boolean
Pre Stack is metadata structure to a valid stack
Post Returns stack status
Return true if stack empty, false if stack contains data
1. if (stack count is 0)
1. return true
2. else
1. return false
3. end if
end emptystack
f. Full stack
It is another structured programming implementation of data hiding.
Depending on the language, it may also be one of the most difficult algorithms and no direct
way to implement.
The pseudo code for full stack is shown in algorithm
Algorithm: Full stack
Algorithm fullstack(stack)
Determined if stack is full and returns a Boolean
Pre stack is metadata structure to a valid stack
Post returns stack status
Return true if stack full, false is memory available
1. if(memory not available)
1. return true
2. else
1. return false
3. end if
end fullstack
g. Stack Count:
Stack count returns the number of elements currently in the stack. It is another implementation
of the data – hiding principle of structured programming.
The pseudo code is shown in algorithm.
Algorithm: stack count
Algorithm stackcount (stack)
Returns the number of elements currently in stack
Pre stack is metadata structure to a valid stack
Post returns stack count
Return integer count of the number of elements in the stack
1. return (stack count)
end stackcount
h. Destroy stack
It deletes all data in a stack
Algorithm: Destroy stack
Algorithm destroystack (stack)
This algorithm releases all nodes back to the dynamic memory
Pre stack passed by reference
Post stack empty and all nodes deleted
1. if (stack is not empty)
1. loop (stack not empty)
1. delete top node
2. end loop
2. end if
3. delete stack head
end destroystack
C Implementation
#include<stdio.h>
#include<conio.h>
#include<stdlib.h>
#define NULL 0
struct data
{
int info;
struct data *next;
};
struct stack
{
int count;
struct data *top;
}*head;
typedef struct stack hnode;
typedef struct data dnode;
dnode *pnew,*dptr,*list;
void createstack();
void push();
void pop();
void print();
void main()
{
int ch;
clrscr();
do
{
printf("\n1.create stack");
printf("\n2.push");
printf("\n3.pop");
printf("\n4.print");
printf("\n5.exit");
printf("\nEnter choice:\n");
scanf("%d",&ch);
switch(ch)
{
case 1: createstack();
break;
case 2: push();
break;
case 3: pop();
break;
case 4: print();
break;
case 5: exit(0);
break;
}
}while(ch!=5);
}
void createstack()
{
head=(hnode *)malloc(sizeof(hnode));
head->count=0;
head->top=NULL;
}
void push()
{
pnew=(dnode *)malloc(sizeof(dnode));
printf("Enter the element");
scanf("%d",&pnew->info);
pnew->next=head->top;
head->top=pnew;
head->count++;
printf("the number of elements in the stack after pushing are:%d\n",head->count);
}
void pop()
{
if(head->top==NULL)
printf("\nStack is Empty\n");
else
{
dptr=head->top;
printf("the popped element is %d\n",dptr->info);
head->top=dptr->next;
head->count--;
printf("the number of elements in stack after popping are:%d\n",head->count);
}
}
void print()
{
int i;
list=head->top;
if(list==NULL)
printf("\nStack is empty\n");
else
{
printf("\n the stack elements are");
for(i=head->count;i>0;i--)
{
printf("\n%d",list->info);
list=list->next;
}
}
}
Queue head:
It requires two pointers and a count
These fields are stored in the queue head structure.
Other attributes, such as maximum number etc., can be stored in the head node.
The queue head structure is as shown in fig.
Queue data node:
The queue data node contains the user data and a link field pointing to the next node, if any.
These nodes are stored in dynamic memory and are inserted and deleted as requested by using
program.
Its structure is also shown in above fig.
Queue Algorithms:
The four basic queue operations are shown in fig.
Create queue:
Algorithm createQueue
Creates and initializes queue structure.
Pre queue is a metadata structure
Post metadata elements have been initialized
Return queue head
1 allocate queue head
2 set queue front to null
3 set queue rear to null
4 Set count to zero
5 return queue head
end createQueue
Enqueue:
The enqueue is a little more complex
To develop the insertion algorithm, we need to analyze two different queue conditions:
o Insertion into an empty queue
o Insertion into a queue with data
These are operations are shown in fig.
When we insert data into an empty queue, the queue’s front and rear pointers must both be set to
point to the new node.
When we insert data into a queue with data already in it, we must point both the link field in the last
node and the rear pointer to the new node.
If the insert was successful, we return a true; if there is no memory left for the new node, we return
a false.
The pseudo code is shown in algorithm
Dequeue
Dequeue is also a little more complex.
We must ensure that the queue contains data.
If the queue is empty, we have underflow and we return false, indicating that the dequeue was not
successful.
Otherwise, we retrieve the item at the front pointer and move the front pointer to the next item.
If we dequeue the last item the front pointer automatically becomes null, but we must also set to
the rear pointer to null.
These cases are shown in fig.
Empty Queue
Empty queue returns true if the queue is empty and false if the queue contains data.
There are several ways to test for an empty queue.
Checking the queue count is the easiest
The pseudo code is shown in algorithm
Queue Empty
Algorithm emptyQueue (queue)
This algorithm checks to see if a queue is empty.
Pre queue is a metadata structure
Return true if empty, false if queue has data
1 if (queue count equal 0)
1 return true
2 else
1 return false
end emptyQueue
Full Queue
Full queue is another structured programming implementation of data hiding.
Depending on language, it may be one of the most difficult algorithms to implement provides no
direct way to implement it.
Te pseudo code is show in algorithm
Full Queue
Algorithm fullQueue (queue)
This algorithm checks to see if a queue is full. The queue is full if memory cannot be allocated for
another node.
Pre queue is a metadata structure
Return true if full, false if room for another node
1 if (memory not available)
1 return true
2 else
1 return false
3 end if
end fullQueue
Queue count
Queue count returns the number of elements currently in the queue by simply returning the count
found in the queue head node.
The Pseudo code is shown in algorithm
Queue count
Algorithm queueCount (queue)
This algorithm returns the number of elements in the queue.
Pre queue is a metadata structure
Return queue count
1 return queue count
end queueCount
Destroy Queue
Destroy queue deletes all data in the queue. The pseudo code is shown in algorithm
Algorithm destroyQueue (queue)
This algorithm deletes all data from a queue.
Pre queue is a metadata structure
Post all data have been deleted
1 if (queue not empty)
1 loop (queue not empty)
1 delete front node
2 end loop
2 end if
3 delete head structure
end destroy Queue
C Implementation
queueadt.h
struct node
{
int data;
struct node *link;
}*newptr,*dptr,*list;
struct queue
{
struct node *front;
struct node *rear;
int count;
}*head;
typedef struct node dnode;
typedef struct queue hnode;
void createqueue()
{
head=(hnode*)malloc(sizeof(hnode));
head->front=NULL;
head->rear=NULL;
head->count=0;
}
void enqueue()
{
newptr=(dnode *)malloc(sizeof(dnode));
printf("enter the data to be inserted:\n");
scanf("%d",&newptr->data);
if(queueempty())
head->front=newptr;
else
head->rear->link=newptr;
head->rear=newptr;
newptr->link=NULL;
head->count++;
}
void dequeue()
{
if(queueempty())
{
head->rear=NULL;
printf("Queue is underflow\n");
// exit(0);
}
else
{
dptr=head->front;
printf("the element deleted is:%d",dptr->data);
head->front=dptr->link;
head->count--;
}
}
void display()
{
int c;
if(queueempty())
{
printf("Queue is underflow\n");
//exit(0);
}
else
{
list=head->front;
c=head->count;
printf("the queue elements are:\n");
while(c>0)
{
printf("%d ",list->data);
list=list->link;
c--;
}
}
}
int queueempty()
{
if(head->count==0)
return 1;
else
return 0;
}
program
#include<stdio.h>
#include<conio.h>
#include"queueadt.h"
void main()
{
int ch;
clrscr();
printf("Queue operations menu\n");
printf("1.createqueue\n2.enqueue\n3.dequeue\n4.display\n5.exit\n");
do
{
printf("\nenter your choice\n");
scanf("%d",&ch);
switch(ch)
{
case 1:createqueue();
break;
case 2:enqueue();
break;
case 3:dequeue();
break;
case 4:display();
break;
case 5:exit(0);
default: printf("not a valid choice\n");
}
}while(ch!=5);
getch();
}
Output