0% found this document useful (0 votes)
68 views

Stack Recursion Quick Sort Word

The document discusses stacks, which are linear data structures that only allow insertion and removal of elements from one end, called the top. Common stack operations like push and pop are described, along with different representations of stacks using arrays and linked lists. Recursive algorithms and examples like Towers of Hanoi that can be solved using stacks are also mentioned.

Uploaded by

raj
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
68 views

Stack Recursion Quick Sort Word

The document discusses stacks, which are linear data structures that only allow insertion and removal of elements from one end, called the top. Common stack operations like push and pop are described, along with different representations of stacks using arrays and linked lists. Recursive algorithms and examples like Towers of Hanoi that can be solved using stacks are also mentioned.

Uploaded by

raj
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 38

Sweta Bohra

Stack
The Linear list and linear array allows us to insert or
delete elements at any place in the list :
At the beginning.
At the end.
Or in the middle.

There are certain frequent situation where we want to


restrict insertion or deletion any at the end of the list.

A stack is a list of element in which an element may be


inserted or deleted only at one end called top of the
stack.
This means in particular time elements are removed from
a stack to the reverse order of that in which they were
inserted into the stack.

Operations on the stack:


There are two basic operations associated with stack.

1. Push : It is the term used to insert an element into


a stack.
Sweta Bohra

2. Pop : It is the term used to delete an element


from a stack.

Representation of stack
Stack may be represented in various ways usually by
means of a one way list or linear array.

Array representation of stack


Let Stack will be maintained by a linear array Stack:
A pointer variable TOS, which contains the location of the
top elements of the stack & a variable MAX gives the
maximum number of the element that can be filled by
the stack.

The operation of adding an item(Push) onto a stack is as


follows.
In the algorithm of TOS=max then we pointed message
as “Stack Overflow” otherwise push an item onto a Stack.

PUSH Operation
Algorithm : Push an element in Stack.
PUSH(STACK, TOS, max, Item)
Step 1: If (TOS = max)
print “overflow condition”
Endif
Step 2: TOS=TOS+1.
Step 3: STACK[TOS] = Item.
Step 4: END.
Sweta Bohra

POP Operation
Algorithm : Pop an element in Stack.
POP(STACK, TOS, max, Item)
Step 1: If (TOS = -1)
print “underflow condition”
Endif
Step 2: Item = STACK[TOS}
Step 3: TOS = TOS - 1
Step 4: END.
Sweta Bohra

Linked representation of Stack

Algorithm: Adding node in Linked List (PUSH)


PUSH(Value)
Step 1. NewNode = Request for Memory Allocation
Step 2. NewNode->Info = Value
Step 3. If TOS = NULL
TOS=NewNode
Else
NewNode->Next = TOS
TOS=NewNode
Step 4. End

CASE 1: if START is NULL (Empty List)

`
TOS TOS

501 501

-1 Pen 51 501 Pen 51

NewNode NewNode
501 501

CASE 1: if START is Not NULL

TOS
501 51 101 211

501 Pen 51 Eraser 101 Pencil 211 Paper NULL

212

NULL
Colour

NewNode
212
Sweta Bohra

TOS
501 51 101 211

212 51 101 211 NULL


Pen Eraser Pencil Paper

212

Colour 501

NewNode
212

Algorithm: Deleting node in Linked List (POP)


DELETE_FIRST(START)
Step 1. If (TOS = NULL) // List Empty
Return -1
Step 2. Val = TOS->Val
Step 3. TOS = TOS->Next
Step 4. Return Val

TOS
501 51 101 211

501 Pen 51 Eraser 412 Pencil 211 Paper NULL

TOS 501

Pen 51 51 101 211

51 Eraser 412 Pencil 211 Paper NULL


Sweta Bohra

Arithmetic Expression

Let
Q is an Arithmetic expression involving constant and
operations.

We will find value of Q by using

Reverse Polish notation (POSTFix notation),


and STACK

Following 3 levels of precendance for usual 5 binary


operations

Highest : Exponentiation ()


Next Highest : Multiplication (*) and Division (/)
Lowest : Addition (+) and Subtration (-)

For simplicity
we use BINARY operations
No UNARY operations
Operations performed left to right

Notations are of 3 types


1. PreFix (Polish Notation)
+AB Opr OpRand OpRand

2. InFix
A+B OpRand Opr OpRand

3. PostFix (Reverse Polish Notation)


AB+ OpRand OpRand Opr
Sweta Bohra

The compiler usually evaluates Infix Expression in 2 steps


1. Convert Infix to Postfix Expression
2. Evaluation of Postfix Expression
And in both the cases STACK is important

First we will learn

1. Evaluation of Postfix Notation

Suppose P is an Arithmetic expression


(postfix expression)
Algorithm will use Stack to hold Operands

Step 1. ADD “)” at End of P

Step 2. Val = Scan P from Left to Right and Repeat Step 3 to 6

Untill “)” encountered

Step 3. If (Val = Operand)

PUSH(Val)

Step 4. If(Val = Operator)

V1 = POP()

V2 = POP()

Step 5. Res = Eval(V1 Val V2)

Step 6. PUSH(Res)

Step 7. FinalRes = POP()


Sweta Bohra

Now let us consider the following infix expression


2 * (4+3) - 5.
Its equivalent postfix expression is
2 4 3 + * 5.

The following step illustrates how this postfix expression


is evaluated.
Sweta Bohra

2. Infix to Postfix Notation

Let Q, Arithmetic Expression in InFix notation


Having
Operators
Exponentiation ()
Multiplication (*)
Division (/)
Addition (+) and
Subtraction (-) with 3 level precedence
(if on same level LEFT to RIGHT)
Operands
( left parenthesis
) right parenthesis

Algorithm
o Uses STACK to hold Operators and (.
o Will be constructed from Left to Right using
 Operands from Q
 Operators which are removed from STACK
o Fds
Sweta Bohra

Suppose Q is Infix Expression

Step 1. PUSH (
Step 2. ADD ) at End of Q
Step 3. Scan Q from Left to Right
Step 4. Repeat Step _ to _ Until Stack is Empty
Step 5. If OPERAND
ADD it to P
Step 6. If (
PUSH (
Step 7. If OPEARTOR
a. Val = POP and ADD to P
Until having same precedence and
higher precedence than Val
b. PUSH Val
Step 8. If )
a. Val = POP and ADD to P
Until ( encountered
b. Remove (; but not add to P
Step 9. Exit
Sweta Bohra

Infix expression: K + L - M*N + (O^P) * W/U/V * T + Q

Input Stack Postfix Expression


Expression

K K

+ + K

L + KL

- - K L+

M - K L+ M

* -* K L+ M

N -* KL+MN

+ + K L + M N*
K L + M N* -

( +( K L + M N *-

O +( KL+MN*-O

^ +(^ K L + M N* - O

P +(^ K L + M N* - O P

) + K L + M N* - O P ^

* +* K L + M N* - O P ^

W +* K L + M N* - O P ^ W

/ +/ K L + M N* - O P ^ W *

U +/ K L + M N* - O P ^W*U
Sweta Bohra

/ +/ K L + M N* - O P ^W*U/

V +/ KL + MN*-OP^W*U/V

* +* KL+MN*-OP^W*U/V/

T +* KL+MN*-OP^W*U/V/T

+ + KL+MN*-OP^W*U/V/T*
KL+MN*-OP^W*U/V/T*+

Q + KL+MN*-OP^W*U/V/T*Q

KL+MN*-OP^W*U/V/T*+Q+

The final postfix expression of infix expression(K + L - M*N + (O^P) * W/U/V *


T + Q) is KL+MN*-OP^W*U/V/T*+Q+.
Sweta Bohra

Recursion

The process in which a function calls itself directly or


indirectly is called recursion and the corresponding
function is called as recursive function. Using recursive
algorithm, certain problems can be solved quite easily.
Examples of such problems are Towers of Hanoi
(TOH), Inorder/Preorder/Postorder Tree Traversals, DFS
of Graph, etc.

Let us consider a problem that a programmer have to


determine the sum of first n natural numbers, there are
several ways of doing that but the simplest approach is
simply add the numbers starting from 1 to n. So the
function simply looks like,

APPROACH(1) – Simply adding one by one


f(n) = 1 + 2 + 3 +……..+ n
but there is another mathematical approach of
representing this,

APPROACH(2) – Recursive adding


f(n) = 1 n=1
f(n) = n + f(n-1) n>1

There is a simple difference between the approach (1)


and approach(2) and that is in approach(2) the function
“ f( ) ” itself is being called inside the function, so this
phenomenon is named as recursion and the function
containing recursion is called recursive function, at the
end this is a great tool in the hand of the programmers to
code some problems in a lot easier and efficient way.
Sweta Bohra

What is base condition in recursion?

In the recursive program, the solution to the base case is


provided and the solution of the bigger problem is
expressed in terms of smaller problems.

int fact(int n)
{
if (n < = 1) // base case
return 1;
else
return n*fact(n-1);
}

In the above example, base case for n < = 1 is defined


and larger value of number can be solved by converting
to smaller one till base case is reached.

How a particular problem is solved using recursion?

The idea is to represent a problem in terms of one or


more smaller problems, and add one or more base
conditions that stop the recursion. For example, we
compute factorial n if we know factorial of (n-1). The
base case for factorial would be n = 0. We return 1 when
n = 0.
Sweta Bohra

Why Stack Overflow error occurs in recursion?

If the base case is not reached or not defined, then the


stack overflow problem may arise. Let us take an
example to understand this.

int fact(int n)
{
// wrong base case (it may cause
// stack overflow).
if (n == 100)
return 1;

else
return n*fact(n-1);
}

If fact(10) is called, it will call fact(9), fact(8), fact(7) and


so on but the number will never reach 100. So, the base
case is not reached. If the memory is exhausted by these
functions on the stack, it will cause a stack overflow
error.

What is the difference between direct and indirect


recursion?

A function fun is called direct recursive if it calls the same


function fun. A function fun is called indirect recursive if it
calls another function say fun_new and fun_new calls fun
directly or indirectly. Difference between direct and
indirect recursion has been illustrated in Table 1.
Sweta Bohra

// An example of direct recursion


void directRecFun()
{
// Some code....

directRecFun();

// Some code...
}

// An example of indirect recursion


void indirectRecFun1()
{
// Some code...
indirectRecFun2();
// Some code...
}
void indirectRecFun2()
{
// Some code...
indirectRecFun1();
// Some code...
}
Sweta Bohra

What is difference between tailed and non-tailed


recursion?

A recursive function is tail recursive when recursive call is


the last thing executed by the function.

A recursive function is tail recursive when a recursive call


is the last thing executed by the function. For example
the following C++ function print() is tail recursive.

// An example of tail recursive function


void print(int n)
{
if (n < 0) return;
cout << " " << n;

// The last executed statement is recursive


call
print(n-1);
}

How memory is allocated to different function calls


in recursion?

When any function is called from main(), the memory is


allocated to it on the stack. A recursive function calls
itself, the memory for a called function is allocated on top
of memory allocated to calling function and different copy
of local variables is created for each function call. When
the base case is reached, the function returns its value to
the function by whom it is called and memory is de-
Sweta Bohra

allocated and the process continues.


Let us take the example how recursion works by taking a
simple function.
void printFun(int test)
{
if (test < 1)
return;
else {
cout << test << " ";
printFun(test - 1); // statement 2
cout << test << " ";
return;
}
}

// Driver Code
int main()
{
int test = 3;
printFun(test);
}
Output :
3 2 1 1 2 3
When printFun(3) is called from main(), memory is
allocated to printFun(3) and a local variable test is
initialized to 3 and statement 1 to 4 are pushed on the
stack as shown in below diagram. It first prints ‘3’. In
Sweta Bohra

statement 2, printFun(2) is called and memory is


allocated to printFun(2) and a local variable test is
initialized to 2 and statement 1 to 4 are pushed in the
stack.

Similarly, printFun(2) calls printFun(1) and printFun(


1) calls printFun(0). printFun(0) goes to if statement
and it return to printFun(1). Remaining statements
of printFun(1) are executed and it returns
to printFun(2) and so on. In the output, value from 3 to
1 is printed and then 1 to 3 are printed. The memory
stack has been shown in below diagram.
Sweta Bohra
Sweta Bohra

Factorial

The following example calculates the factorial of a given


number using a recursive function –

#include <stdio.h>

unsigned long long int factorial(unsigned int i)


{

if(i <= 1) {
return 1;
}
return i * factorial(i - 1);
}

int main() {
int i = 12;
printf("Factorial of %d is %d\n", i,
factorial(i));
return 0;
}

Output
Factorial of 12 is 479001600
Sweta Bohra
Sweta Bohra

Fibonacci Series
The following example generates the Fibonacci series for
a given number using a recursive function –

#include <stdio.h>

int fibonacci(int i) {

if(i == 0) {
return 0;
}

if(i == 1) {
return 1;
}
return fibonacci(i-1) + fibonacci(i-2);
}

int main() {

int i;

for (i = 0; i < 10; i++) {


printf("%d\t\n", fibonacci(i));
}

return 0;
}

When the above code is compiled and executed, it


produces the following result −
0 1 1 2 3 5 8 13 21 34
Sweta Bohra
Sweta Bohra

Tower of Hanoi
Tower of Hanoi is a mathematical puzzle where we have
three rods and n disks. The objective of the puzzle is to move
the entire stack to another rod, obeying the following simple
rules:

 Only one disk can be moved at a time.


 Each move consists of taking the upper disk from one of
the stacks and placing it on top of another stack i.e. a
disk can only be moved if it is the uppermost disk on a
stack.
 No disk may be placed on top of a smaller disk.

Case 1 With 2 Disk

Take an example for 2 disks:


Let rod 1 = 'A', rod 2 = 'B', rod 3 = 'C'.

Step 1 : Shift first disk from 'A' to 'B'.


Step 2 : Shift second disk from 'A' to 'C'.
Step 3 : Shift first disk from 'B' to 'C'.

Output : Disk 1 moved from A to B


Disk 2 moved from A to C
Disk 1 moved from B to C

The pattern here is:


Shift 'n-1' disks from 'A' to 'B'.
Shift last disk from 'A' to 'C'.
Shift 'n-1' disks from 'B' to 'C'.
Sweta Bohra

Case 2 With 3 Disk

Output : Disk 1 moved from A to C


Disk 2 moved from A to B
Disk 1 moved from C to B
Disk 3 moved from A to C
Disk 1 moved from B to A
Disk 2 moved from B to C
Disk 1 moved from A to C
Sweta Bohra

void tower(int a,char from,char aux,char to){


if(a==1){
cout<<"\t\tMove disc 1 from "<<from<<" to "<<to<<"\n";
return;
}
else{
tower(a-1,from,to,aux);
cout<<"\t\tMove disc "<<a<<" from "<<from<<" to "<<to<<"\n";
tower(a-1,aux,from,to);
}
}

void main(){
clrscr();
int n;
cout<<"\n\t\t*****Tower of Hanoi*****\n";
cout<<"\t\tEnter number of discs : ";
cin>>n;
cout<<"\n\n";
tower(n,'A','B','C');
getch();
}
Sweta Bohra
Sweta Bohra
Sweta Bohra

0 A C B

1 A B C A->C

0 C B A
2 A C B A->B

0 B A C
To

Aux
1 B C A B->A
From

0 A C B
3 A B C A->C
0 C B A

1 C A B C->B

0 B A C
2 C B A C->A
0 A C B

1 A B C A->C

0 C B A
Sweta Bohra
Sweta Bohra

QuickSort
Partition Exchange Sort

Application of Stack

Divide and Conquer


o a technique of breaking down the algorithms into subproblems.
o then solving the subproblems, and
o combining the results back together to solve the original problem.

It picks an element as pivot and partitions the given array around the picked
pivot.

There are many different versions of quickSort that pick pivot in different
ways.

o Always pick first element as pivot.


o Always pick last element as pivot (implemented below)
o Pick a random element as pivot.
o Pick median as pivot.

The key process in quickSort is partition().

Target of partitions is
given an array and an element x of array as pivot
put x at its correct position in sorted array
put all smaller elements (smaller than x) before x
put all greater elements (greater than x) after x

Quicksort is the widely used sorting algorithm that makes n log


n comparisons in average case for sorting an array of n elements.
Sweta Bohra

Iteration 1:

10 is Pivot
Put 10 (Pivot) to its correct place

10 5 100 8 9 175 95 6 200 105


P

10 5 100 8 9 175 95 6 200 105


P 5<P 100<P 6>P 200>P 105>P
i i j j j

10 5 100 8 9 175 95 6 200 105


P 5<P 100<P 6>P 200>P 105>P
i i j j j
100 -- 6
10 5 6 8 9 175 95 100 200 105
P 5<P 6<P 8<P 9<p9>P 175>p 95>p 6>P 200>P 105>P
i i i i j i j j j j j

Swap 10 with jth value

9 5 6 8 10 175 95 100 200 105


P j

Now 10 is at its correct place


Sweta Bohra

Iteration 2:
Now the above method will be applied to both the segment
9 is Pivot
Put 9 (Pivot) to its correct place

9 5 6 8 10 175 95 100 200 105


P

9 5 6 8 10 175 95 100 200 105


P 5<P 6<P 8>P
i i i j

Swap 9 with jth value

8 5 6 9 10 175 95 100 200 105


P j

Now 9 is at its correct place


Sweta Bohra

Iteration 3:
Now the above method will be applied to both the segment
8 is Pivot
Put 8 (Pivot) to its correct place

8 5 6 9 10 175 95 100 200 105


P

8 5 6 9 10 175 95 100 200 105


P 5<P 6<P 9>P
i i j j

Swap 8 with jth value

6 5 8 9 10 105 95 100 200 175

Now 8 is at its correct place


Sweta Bohra

Iteration 4:
Now the above method will be applied to both the segment
6 is Pivot
Put 6 (Pivot) to its correct place

6 5 8 9 10 105 95 100 200 175


P

6 5 8 9 10 105 95 100 200 175


P 5<P
i j

Swap 5 with jth value

5 6 8 9 10 105 95 100 200 175

Now 5 is at its correct place


Sweta Bohra

The algorithm works as follows:

QuickSort(LA,BEG,END)
1. If(BEG < END)
2. X=partition(LA,BEG,END)
3. QuickSort(LA,BEG,x-1)
4. QuickSort(LA,x+1,END)
Endif
5. End.

Partition function

Partition(LA,BEG,END)
1. Piv=BEG
2. Repeat while(1)
3. Repeat while(LA[Piv]<=LA[END] and
Piv!=END)
4. END—
[end while]
5. If(Piv = = End)
6. Return Piv
7. Swap(LA[Piv],LA[End])
8. Piv=End
9. Repeat while(LA[Piv]>=LA[BEG]and
Piv!=BEG)
Sweta Bohra

10. BEG++
11. If(Piv= =BEG)
12. Return Piv
13. Swap(LA[Piv],LA[BEG])
14. Piv=BEG
[end while]
15. End.

Swap(LA,BEG,END)
1. Temp=LA[Piv]
2. LA[Piv]=LA[END}
3. LA[END]=Temp
4. End.

You might also like