Stacks Data Structure
Stacks Data Structure
Working of Stack
Stack works on the LIFO pattern. As we can observe in the below figure
there are five memory blocks in the stack; therefore, the size of the stack
is 5.
Suppose we want to store the elements in a stack and let's assume that
stack is empty. We have taken the stack of size 5 as shown below in
which we are pushing the elements one by one until the stack becomes
full.
Since our stack is full as the size of the stack is 5. In the above cases, we
can observe that it goes from the top to the bottom when we were
entering the new element in the stack. The stack gets filled up from the
bottom to the top.
When we perform the delete operation on the stack, there is only one
way for entry and exit as the other end is closed. It follows the LIFO
pattern, which means that the value entered first will be removed last. In
the above case, the value 5 is entered first, so it will be removed only
after the deletion of all the other elements.
C NITHISHA – SOCTS0369
PUSH operation
The steps involved in the PUSH operation is given below:
Push:
Adds an item to the stack. If the stack is full, then it is said to be an
Overflow condition.
Algorithm for push:
begin
if stack is full
return
endif
else
increment top
stack[top] assign value
end else
end procedure
POP operation
The steps involved in the POP operation is given below:
o Before deleting the element from the stack, we check whether the
stack is empty.
o If we try to delete the element from the empty stack, then
the underflow condition occurs.
o If the stack is not empty, we first access the element which is
pointed by the top
C NITHISHA – SOCTS0369
Pop:
Removes an item from the stack. The items are popped in the reversed
order in which they are pushed. If the stack is empty, then it is said to be
an Underflow condition.
Algorithm for pop:
begin
if stack is empty
return
endif
C NITHISHA – SOCTS0369
else
store value of stack[top]
decrement top
return value
end else
end procedure
Top:
Returns the top element of the stack.
Algorithm for Top:
begin
return stack[top]
end procedure
isEmpty:
Returns true if the stack is empty, else false.
Algorithm for isEmpty:
begin
if top < 1
return true
C NITHISHA – SOCTS0369
else
return false
end procedure
Implementation of Stack:
The basic operations that can be performed on a stack include push, pop,
and peek. There are two ways to implement a stack –
Using array
Using linked list
1. Increment the variable Top so that it can now refere to the next
memory location.
2. Add element at the position of incremented top. This is referred to
as adding new element at the top of the stack.
C NITHISHA – SOCTS0369
Algorithm:
1. begin
2. if top = n then stack full
3. top = top + 1
4. stack (top) : = item;
5. end
Deletion of an element from the top of the stack is called pop operation.
The value of the variable top will be incremented by 1 whenever an item
is deleted from the stack. The top most element of the stack is stored in
an another variable and then the top is decremented by 1. the operation
returns the deleted value that was stored in another variable as the result.
Algorithm :
1. begin
2. if top = 0 then stack empty;
3. item := stack(top);
4. top = top - 1;
5. end;
1. int pop ()
2. {
3. if(top == -1)
4. {
5. printf("Underflow");
6. return 0;
7. }
C NITHISHA – SOCTS0369
8. else
9. {
10. return stack[top - - ];
11. }
12. }
Peek operation involves returning the element which is present at the top
of the stack without deleting it. Underflow condition can occur if we try
to return the top element in an already empty stack.
Algorithm :
1. Begin
2. if top = -1 then stack empty
3. item = stack[top]
4. return item
5. End
1. int peek()
2. {
3. if (top == -1)
C NITHISHA – SOCTS0369
4. {
5. printf("Underflow");
6. return 0;
7. }
8. else
9. {
10. return stack [top];
11. }
12. }
The top most node in the stack always contains null in its address field.
Lets discuss the way in which, each operation is performed in linked list
implementation of stack.
C implementation :
1. void push ()
2. {
3. int val;
4. struct node *ptr =(struct node*)malloc(sizeof(struct node))
;
C NITHISHA – SOCTS0369
5. if(ptr == NULL)
6. {
7. printf("not able to push the element");
8. }
9. else
10. {
11. printf("Enter the value");
12. scanf("%d",&val);
13. if(head==NULL)
14. {
15. ptr->val = val;
16. ptr -> next = NULL;
17. head=ptr;
18. }
19. else
20. {
21. ptr->val = val;
22. ptr->next = head;
23. head=ptr;
24.
25. }
26. printf("Item pushed");
27.
28. }
29. }
C NITHISHA – SOCTS0369
C implementation
1.void pop()
2.{
3. int item;
4. struct node *ptr;
5. if (head == NULL)
6. {
C NITHISHA – SOCTS0369
7. printf("Underflow");
8. }
9. else
10. {
11. item = head->val;
12. ptr = head;
13. head = head->next;
14. free(ptr);
15. printf("Item popped");
16.
17. }
18. }
Displaying all the nodes of a stack needs traversing all the nodes of
the linked list organized in the form of stack. For this purpose, we
need to follow the following steps.
C Implementation
1.void display()
2.{
C NITHISHA – SOCTS0369
3. int i;
4. struct node *ptr;
5. ptr=head;
6. if(ptr == NULL)
7. {
8. printf("Stack is empty\n");
9. }
10. else
11. {
12. printf("Printing Stack elements \n");
13. while(ptr!=NULL)
14. {
15. printf("%d\n",ptr->val);
16. ptr = ptr->next;
17. }
18. }
19. }
C NITHISHA – SOCTS0369
3. For example, people waiting in line for a rail ticket form a queue.
Applications of Queue
Due to the fact that queue performs actions on first in first out basis
which is quite fair for the ordering of actions. There are various
applications of queues discussed as below.
1. Queues are widely used as waiting lists for a single shared resource
like printer, disk, CPU.
C NITHISHA – SOCTS0369
Complexity
C NITHISHA – SOCTS0369
The above figure shows the queue of characters forming the English
word "HELLO". Since, No deletion is performed in the queue till now,
therefore the value of front remains -1 . However, the value of rear
increases by one every time an insertion is performed in the queue. After
inserting an element into the queue shown in the above figure, the queue
will look something like following. The value of rear will become 5
while the value of front remains same.
C NITHISHA – SOCTS0369
If the item is to be inserted as the first element in the list, in that case set
the value of front and rear to 0 and insert the element at the rear end.
Otherwise keep increasing the value of rear and insert each element one
by one having rear as the index.
Algorithm
C Function
1. void insert (int queue[], int max, int front, int rear, int item)
2. {
3. if (rear + 1 == max)
C NITHISHA – SOCTS0369
4. {
5. printf("overflow");
6. }
7. else
8. {
9. if(front == -1 && rear == -1)
10. {
11. front = 0;
12. rear = 0;
13. }
14. else
15. {
16. rear = rear + 1;
17. }
18. queue[rear]=item;
19. }
20. }
If, the value of front is -1 or value of front is greater than rear , write an
underflow message and exit.
Otherwise, keep increasing the value of front and return the item stored
at the front end of the queue at each time.
Algorithm
Write UNDERFLOW
ELSE
C NITHISHA – SOCTS0369
C Function
1. int delete (int queue[], int max, int front, int rear)
2. {
3. int y;
4. if (front == -1 || front > rear)
5.
6. {
7. printf("underflow");
8. }
9. else
10. {
11. y = queue[front];
12. if(front == rear)
13. {
14. front = rear = -1;
15. else
16. front = front + 1;
17.
18. }
19. return y;
20. }
21. }
C NITHISHA – SOCTS0369
Although, the technique of creating a queue is easy, but there are some
drawbacks of using this technique to implement a queue.
The above figure shows how the memory space is wasted in the array
representation of queue. In the above figure, a queue of size 10 having 3
elements, is shown. The value of the front variable is 5, therefore, we
can not reinsert the values in the place of already deleted element before
the position of front. That much space of the array is wasted and can not
be used in the future (for this queue).
we can store queue elements as enough as possible but the main problem
with this declaration is that, most of the array slots (nearly half) can
never be reused. It will again lead to memory wastage.
In a linked queue, each node of the queue consists of two parts i.e. data
part and the link part. Each element of the queue points to its immediate
next element in the memory.
In the linked queue, there are two pointers maintained in the memory i.e.
front pointer and rear pointer. The front pointer contains the address of
the starting element of the queue while the rear pointer contains the
address of the last element of the queue.
Insertion and deletions are performed at rear and front end respectively.
If front and rear both are NULL, it indicates that the queue is empty.
C NITHISHA – SOCTS0369
There are two basic operations which can be implemented on the linked
queues. The operations are Insertion and Deletion.
Insert operation
The insert operation append the queue by adding an element to the end
of the queue. The new element will be the last element of the queue.
Firstly, allocate the memory for the new node ptr by using the following
statement.
There can be the two scenario of inserting this new node ptr into the
linked queue.
In the first scenario, we insert element into an empty queue. In this case,
the condition front = NULL becomes true. Now, the new element will
be added as the only element of the queue and the next pointer of front
and rear pointer both, will point to NULL.
In the second case, the queue contains more than one element. The
condition front = NULL becomes false. In this scenario, we need to
update the end pointer rear so that the next pointer of rear will point to
the new node ptr. Since, this is a linked queue, hence we also need to
C NITHISHA – SOCTS0369
make the rear pointer point to the newly added node ptr. We also need
to make the next pointer of rear point to NULL.
In this way, the element is inserted into the queue. The algorithm and the
C implementation is given as follows.
Algorithm
C Function
Deletion
Deletion operation removes the element that is first inserted among all
the queue elements. Firstly, we need to check either the list is empty or
not. The condition front == NULL becomes true if the list is empty, in
this case , we simply write underflow on the console and make exit.
C NITHISHA – SOCTS0369
1. ptr = front;
2. front = front -> next;
3. free(ptr);
Algorithm
o Step 1: IF FRONT = NULL
o Write " Underflow "
o Go to Step 5
o [END OF IF]
o Step 2: SET PTR = FRONT
o Step 3: SET FRONT = FRONT -> NEXT
o Step 4: FREE PTR
o Step 5: END
C Function
8. else
9. {
10. ptr = front;
11. front = front -> next;
12. free(ptr);
13. }
14. }
C NITHISHA – SOCTS0369
Circular Queue
Why was the concept of the circular queue introduced?
As we can see in the above image, the rear is at the last position of the
Queue and front is pointing somewhere rather than the 0 th position. In
the above array, there are only two elements and other three positions
are empty. The rear is at the last position of the Queue; if we try to insert
the element then it will show that there are no empty spaces in the
Queue. There is one solution to avoid such wastage of memory space by
shifting both the elements at the left and adjust the front and rear end
accordingly. It is not a practically good approach because shifting all the
C NITHISHA – SOCTS0369
elements will consume lots of time. The efficient approach to avoid the
wastage of the memory is to use the circular queue data structure.
Enqueue operation
o When front ==0 && rear = max-1, which means that front is at
the first position of the Queue and rear is at the last position of the
Queue.
o front== rear + 1;
C NITHISHA – SOCTS0369
Dequeue Operation
Step 1: IF FRONT = -1
Write " UNDERFLOW "
Goto Step 4
[END of IF]
Step 2: SET VAL = QUEUE[FRONT]
Step 3: IF FRONT = REAR
SET FRONT = REAR = -1
ELSE
IF FRONT = MAX -1
SET FRONT = 0
ELSE
SET FRONT = FRONT + 1
[END of IF]
[END OF IF]
Step 4: EXIT
C NITHISHA – SOCTS0369
As we know that linked list is a linear data structure that stores two
parts, i.e., data part and the address part where address part contains the
address of the next node. Here, linked list is used to implement the
circular queue; therefore, the linked list follows the properties of the
Queue. When we are implementing the circular queue using linked list
then both the enqueue and dequeue operations take O(1) time.
C NITHISHA – SOCTS0369
The deque stands for Double Ended Queue. Deque is a linear data
structure where the insertion and deletion operations are performed from
both ends. We can say that deque is a generalized version of the queue.
Types of deque
o Insertion at front
o Insertion at rear
o Deletion at front
o Deletion at rear
C NITHISHA – SOCTS0369
We can also perform peek operations in the deque along with the
operations listed above. Through peek operation, we can get the deque's
front and rear elements of the deque. So, in addition to the above
operations, following operations are also supported in deque -
In this operation, the element is inserted from the front end of the queue.
Before implementing the operation, we first have to check whether the
queue is full or not. If the queue is not full, then the element can be
inserted from the front end by using the below conditions -
o If the queue is empty, both rear and front are initialized with 0.
Now, both will point to the first element.
o Otherwise, check the position of the front if the front is less than 1
(front < 1), then reinitialize it by front = n - 1, i.e., the last index of
the array.
C NITHISHA – SOCTS0369
In this operation, the element is inserted from the rear end of the queue.
Before implementing the operation, we first have to check again whether
the queue is full or not. If the queue is not full, then the element can be
inserted from the rear end by using the below conditions –
o If the queue is empty, both rear and front are initialized with 0.
Now, both will point to the first element.
o Otherwise, increment the rear by 1. If the rear is at last index (or
size - 1), then instead of increasing it by 1, we have to make it
equal to 0.
C NITHISHA – SOCTS0369
In this operation, the element is deleted from the front end of the queue.
Before implementing the operation, we first have to check whether the
queue is empty or not.
If the queue is empty, i.e., front = -1, it is the underflow condition, and
we cannot perform the deletion. If the queue is not full, then the element
can be inserted from the front end by using the below conditions -
If the deque has only one element, set rear = -1 and front = -1.
Else if front is at end (that means front = size - 1), set front = 0.
In this operation, the element is deleted from the rear end of the queue.
Before implementing the operation, we first have to check whether the
queue is empty or not.
If the queue is empty, i.e., front = -1, it is the underflow condition, and
we cannot perform the deletion.
If the deque has only one element, set rear = -1 and front = -1.
Check empty
Check full
The time complexity of all of the above operations of the deque is O(1),
i.e., constant.
Applications of deque
o Deque can be used as both stack and queue, as it supports both
operations.
o Deque can be used as a palindrome checker means that if we read
the string from both ends, the string would be the same.
C NITHISHA – SOCTS0369
Priority Queue
What is a priority queue?
1, 3, 4, 8, 14, 22
C NITHISHA – SOCTS0369
All the values are arranged in ascending order. Now, we will observe
how the priority queue will look after performing the following
operations:
o poll(): This function will remove the highest priority element from
the priority queue. In the above priority queue, the '1' element has
the highest priority, so it will be removed from the priority queue.
o add(2): This function will insert '2' element in a priority queue. As
2 is the smallest element among all the numbers so it will obtain
the highest priority.
o poll(): It will remove '2' element from the priority queue as it has
the highest priority queue.
o add(5): It will insert 5 element after 4 as 5 is larger than 4 and
lesser than 8, so it will obtain the third highest priority in a priority
queue.
Now, we will see how to represent the priority queue through a one-way
list.
We will create the priority queue by using the list given below in
which INFO list contains the data elements, PRN list contains the
priority numbers of each data element available in the INFO list, and
LINK basically contains the address of the next node.
Step 1: In the list, lower priority number is 1, whose data value is 333,
so it will be inserted in the list as shown in the below diagram:
So, this data will be inserted based on the FIFO principle; therefore 222
will be added first and then 111.
Step 3: After inserting the elements of priority 2, the next higher priority
number is 4 and data elements associated with 4 priority numbers are
444, 555, 777. In this case, elements would be inserted based on the
FIFO principle; therefore, 444 will be added first, then 555, and then
777.
Step 4: After inserting the elements of priority 4, the next higher priority
number is 5, and the value associated with priority 5 is 666, so it will be
inserted at the end of the queue.
The priority queue can be implemented in four ways that include arrays,
linked list, heap data structure and binary search tree. The heap data
structure is the most efficient way of implementing the priority queue, so
we will implement the priority queue using a heap data structure in this
topic. Now, first we understand the reason why heap is the most efficient
way among all the other data structures.
What is Heap?
o Max heap: The max heap is a heap in which the value of the
parent node is greater than the value of the child nodes.
C NITHISHA – SOCTS0369
o Min heap: The min heap is a heap in which the value of the parent
node is less than the value of the child nodes.
Both the heaps are the binary heap, as each has exactly two child nodes.
If the element is not in a correct place then it is compared with the parent
node; if it is found out of order, elements are swapped. This process
continues until the element is placed in a correct position.
C NITHISHA – SOCTS0369
As we know that in a max heap, the maximum element is the root node.
When we remove the root node, it creates an empty slot. The last
inserted element will be added in this empty slot. Then, this element is
compared with the child nodes, i.e., left-child and right child, and swap
C NITHISHA – SOCTS0369
with the smaller of the two. It keeps moving down the tree until the heap
property is restored.