Unit-III
Unit-III
Stack Representation
The following fig 3.1 depicts a stack and its operations −
A stack can be implemented by means of Array, Structure, Pointer, and Linked List. Stack can
either be a fixed size one or it may have a sense of dynamic resizing. Here, we are going to implement
stack using arrays, which makes it a fixed size stack implementation. First we have to allocate a
memory block of sufficient size to accommodate the full capacity of the stack. Then, starting from
the first location of the memory block, the items of the stack can be stored in a sequential fashion.
Fig 3.2 Representation of a stack
In Fig 3.2 a, Itemi denotes the ith item in the stack; l and u denote the index range of
the array in use; usually the values of these indices are 1 and SIZE respectively. TOP is a
pointer to point the position of the array up to which it is filled with the items of the stack.
Although array representation of stacks is very easy and convenient but it allows the
representation of only fixed sized stacks. In several applications, the size of the stack may
vary during program execution. An obvious solution to this problem is to represent a stack
using a linked list. A single linked list structure is sufficient to represent any stack. Here,
the DATA field is for the ITEM, and the LINK field is, as usual, to point to the next' item.
Above Figure b depicts such a stack using a single linked list. In the linked list
representation, the first node on the list is the current item that is the item at the top of the
stack and the last node is the node containing the bottom-most item. Thus, a PUSH
operation will add a new node in the front and a POP operation will remove a node from
the front of the list is shown in Fig 3.2 b.
3.4 Stack Operations
Stack operations may involve initializing the stack, using it and then de-initializing it. Apart
from these basic stuffs, a stack is used for the following two primary operations −
• push() − Pushing (storing) an element on the stack.
• pop() − Removing (accessing) an element from the stack.
When data is PUSHed onto stack.
To use a stack efficiently, we need to check the status of stack as well. For the same purpose, the
following functionality is added to stacks −
• peek() − get the top data element of the stack, without removing it.
• isFull() − check if stack is full.
• isEmpty() − check if stack is empty.
At all times, we maintain a pointer to the last PUSHed data on the stack. As this pointer always
represents the top of the stack, hence named top. The top pointer provides top value of the stack
without actually removing it.
3.5 Algorithm for Stack Operations
Push Operation
The process of putting a new data element onto stack is known as a Push Operation is shown in
fig.3.3. Push operation involves a series of steps −
Step 1 − Checks if the stack is full.
Step 2 − If the stack is full, produces an error and exit.
Step 3 − If the stack is not full, increments top to point next empty space.
Step 4 − Adds data element to the stack location, where top is pointing.
Step 5 − Returns success.
if stack is full
return null
endif
top ← top + 1
stack[top] ← data
end procedure
Pop Operation
Accessing the content while removing it from the stack, is known as a Pop Operation. In an array
implementation of pop() operation, the data element is not actually removed, instead top is
decremented to a lower position in the stack to point to the next value. But in linked-list
implementation, pop() actually removes data element and deallocates memory space is shown in
Fig.3.4.
A Pop operation may involve the following steps −
Step 1 − Checks if the stack is empty.
Step 2 − If the stack is empty, produces an error and exit.
Step 3 − If the stack is not empty, accesses the data element at which top is pointing.
Step 4 − Decreases the value of top by 1.
Step 5 − Returns success.
if stack is empty
return null
endif
data ← stack[top]
top ← top - 1
return data
Displays the elements of a Stack
We can use the following steps to display the elements of a stack...
Step 2 - If it is EMPTY, then display "Stack is EMPTY!!!" and terminate the function.
Step 3 - If it is NOT EMPTY, then define a variable 'i' and initialize with top.
Display stack[i] value and decrement i value by one (i--).
Example
We can use the following steps to insert a new node into the stack...
push(int value)
begin
newNode->data = value;
if(top == NULL)
newNode->next = NULL;
else
newNode->next = top;
top = newNode;
end
We can use the following steps to delete a node from the stack...
Step 3 - If it is Not Empty, then define a Node pointer 'temp' and set it to 'top'.
void pop()
begin
if(top == NULL)
print("\nStack is Empty!!!\n");
else
top = temp->next;
free(temp);
endif
end
We can use the following steps to display the elements (nodes) of a stack...
Step 2 - If it is Empty, then display 'Stack is Empty!!!' and terminate the function.
Step 3 - If it is Not Empty, then define a Node pointer 'temp' and initialize with top.
Step 4 - Display 'temp → data --->' and move it to the next node. Repeat the same
until temp reaches to the first node in the stack. (temp → next != NULL).
void display()
begin
if(top == NULL)
print("\nStack is Empty!!!\n");
else{
struct Node *temp = top;
while(temp->next != NULL)
begin
print("%d--->",temp->data);
temp = temp -> next;
end
print("%d--->NULL",temp->data);
end
Disks
Smallest
Largest
Step: 0
Step: 2
END
3.7.2 Infix to postfix Transformation
There is an algorithm to convert an infix expression into a postfix expression. It uses a
stack; but in this case, the stack is used to hold operators rather than numbers. The purpose of the
stack is to reverse the order of the operators in the expression. It also serves as a storage structure,
since no operator can be printed until both of its operands have appeared.
In this algorithm, all operands are printed (or sent to output) when they are read. There are
more complicated rules to handle operators and parentheses.
Example:
1. A * B + C becomes A B * C +
The order in which the operators appear is not reversed. When the '+' is read, it has lower
precedence than the '*', so the '*' must be printed first.
We will show this in a table with three columns. The first will show the symbol currently being
read. The second will show what is on the stack and the third will show the current contents of the
postfix string. The stack will be written from left to right with the 'bottom' of the stack to the left.
current symbol operator stack postfix string
1 A A
2 * * A
3 B * AB
5 C + AB*C
6 AB*C+
The rule used in lines 1, 3 and 5 is to print an operand when it is read. The rule for line 2 is to push
an operator onto the stack if it is empty. The rule for line 4 is if the operator on the top of the stack
has higher precedence than the one being read, pop and print the one on top and then push the new
operator on. The rule for line 6 is that when the end of the expression has been reached, pop the
operators on the stack one at a time and print them.
2. A + B * C becomes A B C * +
Here the order of the operators must be reversed. The stack is suitable for this, since operators will
be popped off in the reverse order from that in which they were pushed.
1 A A
2 + + A
3 B + AB
4 * +* AB
5 C +* ABC
6 ABC*+
In line 4, the '*' sign is pushed onto the stack because it has higher precedence than the '+' sign
which is already there. Then when the are both popped off in lines 6 and 7, their order will be
reversed.
3. A * (B + C) becomes A B C + *
A subexpression in parentheses must be done before the rest of the expression.
1 A A
2 * * A
3 ( *( AB
4 B *( AB
5 + *(+ AB
6 C *(+ ABC
7 ) * ABC+
8 ABC+*
Since expressions in parentheses must be done first, everything on the stack is saved and the left
parenthesis is pushed to provide a marker. When the next operator is read, the stack is treated as
though it were empty and the new operator (here the '+' sign) is pushed on. Then when the right
parenthesis is read, the stack is popped until the corresponding left parenthesis is found. Since
postfix expressions have no parentheses, the parentheses are not printed.
4. A - B + C becomes A B - C +
When operators have the same precedence, we must consider association. Left to right association
means that the operator on the stack must be done first, while right to left association means the
reverse.
current symbol operator stack postfix string
1 A A
2 - - A
3 B - AB
4 + + AB-
5 C + AB-C
6 AB-C+
In line 4, the '-' will be popped and printed before the '+' is pushed onto the stack. Both operators
have the same precedence level, so left to right association tells us to do the first one found before
the second.
5. A * B ^ C + D becomes A B C ^ * D +
Here both the exponentiation and the multiplication must be done before the addition.
1 A A
2 * * A
3 B * AB
4 ^ *^ AB
5 C *^ ABC
6 + + ABC^*
7 D + ABC^*D
8 ABC^*D+
When the '+' is encountered in line 6, it is first compared to the '^' on top of the stack. Since it has
lower precedence, the '^' is popped and printed. But instead of pushing the '+' sign onto the stack
now, we must compare it with the new top of the stack, the '*'. Since the operator also has higher
precedence than the '+', it also must be popped and printed. Now the stack is empty, so the '+' can
be pushed onto the stack.
6. A * (B + C * D) + E becomes A B C D * + * E +
1 A A
2 * * A
3 ( *( A
4 B *( AB
5 + *(+ AB
6 C *(+ ABC
7 * *(+* ABC
8 D *(+* ABCD
9 ) * ABCD*+
10 + + ABCD*+*
11 E + ABCD*+*E
12 ABCD*+*E+
Algorithm
int top = -1;
Infixtopostfix()
begin
print("\n\nRead the Infix Expression ? ");
Read infx
push('#');
while ((ch = infx[i++]) != '\0')
begin
if (ch == '(')
push(ch);
else if (isalnum(ch))
pofx[k++] = ch;
else if (ch == ')')
begin
while (s[top] != '(')
begin
pofx[k++] = pop();
elem = pop(); /* Remove ( */
end
else
while (pr(s[top]) >= pr(ch))
pofx[k++] = pop();
push(ch);
end
end
3.8 Queue
3.8.1 Introduction
Queue is also an abstract data type or a linear data structure, just like stack data structure,
in which the first element is inserted from one end called the REAR(also called tail), and the
removal of existing element takes place from the other end called as FRONT (also called head).
This makes queue as FIFO (First in First Out) data structure, which means that element inserted
first will be removed first. The process to add an element into queue is called Enqueue and the
process of removal of an element from queue is called Dequeue.
ADDQ(x)
If rear = MAX – 1
Then
Print “Queue is full”
Return
Else
Rear = rear + 1
A[rear] = x
If front = -1
Then
Front = 0
End if
End if
End ADDQ( )
Del( )
The del( ) operation deletes the element from the front of the queue. Before deleting and
element, it is checked if the queue is empty. If not the element pointed by front is deleted from
the queue and front is now made to point to the next element in the queue.
DELQ( )
If front = -1
Then
Print “Queue is Empty”
Return
Else
Item = A[front]
A[front] = 0
If front = rear
Then
Front = rear = -1
Else
Front = front + 1
End if
Return item
End if
End DELQ( )
Queue can be represented using a linked list. Linked lists do not have any restrictions on
the number of elements it can hold. Space for the elements in a linked list is allocated dynamically;
hence it can grow as long as there is enough memory available for dynamic allocation. The queue
represented using linked list would be represented as shown. The front pointer points to the front
of the queue and rear pointer points to the rear of the queue is shown in Fig 3.9.
ADDQ(x)
If front = NULL
Then
Rear = front = temp
Return
End if
Link(rear) = temp
Rear = link(rear)
End ADDQ( )
Delq( )
The delq( ) operation deletes the first element from the front end of the queue. Initially it
is checked, if the queue is empty. If it is not empty, then return the value in the node pointed by
front, and moves the front pointer to the next node.
DELQ( )
If front = NULL
Print “Queue is empty”
Return
Else
While front ≠ NULL
Temp = front
Front = link(front)
Delete temp
End while
End if
End DELQ( )
3.8.5 Queue Applications
3.8.5.1 Priority Queue
Priority Queue is more specialized data structure than Queue. Like ordinary queue, priority
queue has same method but with a major difference. In Priority queue items are ordered by key
value so that item with the lowest value of key is at front and item with the highest value of key is
at rear or vice versa is shown in Fig.3.10.
Basic Operations
• insert / enqueue − add an item to the rear of the queue.
• remove / dequeue − remove an item from the front of the queue.
Priority Queue Representation
int removeData(){
return intArray[--itemCount];
}