Lec 5-Stacks and Queues

Post on 16-Nov-2014

120 views 5 download

Tags:

Transcript of Lec 5-Stacks and Queues

Stacks, Queues and Resursion

Stack• A stack is also known as a Last-In-First-Out

(LIFO) list.• A stack is a linear structure in which items are

added or removed only at one end the top. • The depth of stack is the number of elements

it contains.• An empty stack has depth zero.

Stack Example

Stack Operations

• Some stack operations:

– push - add an item to the top of the stack– pop - remove an item from the top of the stack– peek (or top) - retrieves the top item without

removing it– empty – returns false if stack is empty(stack is empty,

can't pop)– full- returns true if stack is full(stack is full, can't insert

new element)

Implementing Stack using Array

xxx yyy zzz

STACK

1 2 3 4 5 6 7 8

3TOP8MAXSTK

PUSH()

• This procedure pushes an ITEM onto a stack

PUSH(STACK,TOP,MAXSTK,ITEM)1. IF TOP = MAXSTK, then

Print : Overflow, and Return2. Set TOP = TOP + 1 [Increase TOP by 1]3. Set STACK[TOP]= ITEM [Insert ITEM in new TOP position]4. Return

POP()

• This procedure deletes the top element of stack and assigns it to the variable ITEM

POP(STACK,TOP,ITEM)1. IF TOP = 0, then

Print : Underflow, and Return2. Set ITEM = STACK[TOP] [Assigns TOP element to ITEM]3. Set TOP= TOP - 1 [Decreases TOP by 1]4. Return

Limitations

• Limitations

– The maximum size of the stack must be defined a priori and cannot be changed

– Trying to push a new element into a full stack causes an implementation-specific exception

Question

• Suppose STACK is allocated N=6 memory cells and initially STACK is empty. Find the output of the following procedure.

1. Set A=2 and B=52. Call PUSH(STACK,A)

Call PUSH(STACK,4)Call PUSH(STACK,B+2) Call PUSH(STACK,9) Call PUSH(STACK,A+B)

1. Repeat while TO!= 0Call POP(STACK,ITEM)

End of lopp

Queue• A queue is also known as a First-In-First-Out

(FIFO) list.• A queue is a linear list of elements in which

deletions can take place only at one end, called the front, and insertion can take place only at the other end called the rear.

Queue Operations

Some queue operations:

– insert - add an item into a queue– delete - deletes an item from the queue– empty - returns false if the queue is empty– full-return true if queue is full

Enqueue and Dequeue

• Primary queue operations: Enqueue and Dequeue• Like check-out lines in a store, a queue has a front and a rear. • Enqueue

– Insert an element at the rear of the queue• Dequeue

– Remove an element from the front of the queue

Insert (Enqueue)

Remove(Dequeue) rearfront

Implementing a Queue using Array

AAA BBB CCC DDD

QUEUE

1 2 3 4 5 6 7 8

Front:1, Rear:4

BBB CCC DDD

QUEUE

1 2 3 4 5 6 7 8

Front:2, Rear:4

Implementing a Queue using Array

BBB CCC DDD EEE FFF

QUEUE

1 2 3 4 5 6 7 8

Front:2, Rear:6

CCC DDD EEE FFF

QUEUE

1 2 3 4 5 6 7 8

Front:3, Rear:6

Circular Queue

• Suppose we want to insert an element into the queue after it occupies the last part of the array i.e. REAR=n.

• One way of doing it is simply move the entire queue to the beginning of the array, changing FRONT and REAR, and then inserting the element. This procedure may be very expensive.

• This can be done assuming that the array QUEUE is circular that is the QUEUE[1] comes after QUEUE[N] in the array. Instead if increasing REAR to N+1 we reset REAR=1.

QINSERT• This procedure inserts an element ITEM into a queue.

QINSERT(QUEUE,N,FRONT,REAR,ITEM)

[Queue already fill]1. If FRONT=1 and REAR=N, or if FRONT=REAR+1,then

Write: Overflow, and Return

2. [Find new value of REAR]If FRONT=NULL, then [Queue initially empty]

Set FRONT=1 and REAR=1Else if REAR =N then

Set REAR=1Else

Set REAR=REAR+1[End of if structure]

3. Set QUEUE[REAR]=ITEM [This inserts new element]4. Return

QDELETE• This procedure deletes an element from the queue and assigns it to

the variable ITEM.

QDELETE(QUEUE,N,FRONT,REAR,ITEM)

[Queue already empty]1. If FRONT=NULL, then

Write: Underflow, and Return

2. Set ITEM=QUEUE[FRONT]3. [Find new value of FRONT]

If FRONT=REAR, then [Queue has only one element to start]Set FRONT=NULL and REAR=NULL

Else if FRONT =N thenSet FRONT =1

Else Set FRONT = FRONT +1

[End of if structure]

4. Return

Question• Consider a circular queue with six memory cells.QUEUE: _,A,C,D,_,_ Front=2,REAR=4a) Add Fb) Two letters are deletec) Add K,L and Md) Two letters are deletee) Add Rf) Two letters are deleteg) Add Sh) Two letters are deletei) One letters are delete j) One letters are delete

Double-Ended-QUE

• A deque is a double-ended que• Insertions and deletions can occur at either

end but not in the middle• Implementation is similar to that for que• Deque are not heavily used

Double-Ended-QUE

AAA BBB CCC DDD

DEQUE

1 2 3 4 5 6 7 8

Left:4, Right:7

YYY ZZZ WWW XXX

DEQUE

1 2 3 4 5 6 7 8

Left:7, Right:2

Double-Ended-QUE

• There are two variations of deque– Input-restricted deque

An input restricted deque is a deque which allows insertion at only one end of the list but allows deletion a both end of the list.

– Output-restricted dequeAn outut restricted deque is a deque which allows deletion at only one end of the list but allows insertin a both end of the list.

Question• Consider a circular DEQUE with six memory

cells.DEQUE:_,A,C,D,_,_ LEFT=2, RIGHT=4a) Add F to the rightb) Two letters are deleted from the rightc) K,L, and M are added to the leftd) One letter on the left is deletede) R is added to the left f) S is added to the rightg) T is added to the right

Priority Queues

• A priority queue is a collection of elements such that each element has been assigned a priority and such that the order in which the elements are deleted and processed comes from the following rules:1. An element of higher priority is processed before

any element of lower priority.2. Two elements of the same priority are processed

according to the order in which they were add to the queue.

Priority Queues Operations

• insert -Add a new item to the queue.

• delete- Remove and return an item from the queue. The item that is returned is the one with the highest priority.

• empty- Check whether the queue is empty.

Polish Notation

• Polish notation named after Polish mathematician Jan Lukasiewiez, refers to the notation in which the operator symbol is placed before its operands.

• Reverse Polish notation refers to the notation in which operator symbol is placed after its operands.

Evaluation of expression

• An expression is made up of operands, operators, and delimiters.

A/B-C+D*E-A*C• Arithmetic operators

+,-,*,/, %, and unary minus• Relational operators

<,<=,==,<.,>=, >, &&, ||, and !.

Priority of operators

• To fix the order of evaluation, each operator is assigned a priority.

• The C++ rule is that for all priorities, evaluation of operators of the same priority will proceed left to right.

A/B*C will be evaluated as (A/B)*C.X=A/B-C+D*E-A*C will be evaluated asX=(((A/B)-C)+(D*E))-(A*C).

Priority of operators

Postfix notation

• A compiler accepts an expression and produces correct code by reworking the expression into a form called postfix notation.

• The conventional way of writing an expression is called infix- the operators come in-between the operands

• Infix A*B/C has postfix AB*C/.Infix: A/B-C+D*E-A*CPostfix: AB/C-DE*+AC*-

Infix to Postfix: Example

A.3 + 5 * 6 – 7 * (8 + 5)=3 5 6 * + 7 8 5 + * – B.A/B-C+D*E-A*C =AB/C-DE*+AC*-C.5+ 3 + 4 + 1=5 3 + 4 + 1 +D.(5 + 3) * 10= 5 3 + 10 * E. (b * b – 4 * a * c) / (2 * a) =b b * 4 a * c * -2 a

* /

Evaluating Arithmetic Expression

• The computer usually evaluate an arithmetic expression written in infix notation in two steps:1. First it converts the expression to postfix

notation, and

2. Then it evaluates the postfix expression.

Evaluation of Postfix Expression

• This algorithm finds the VALUE of an arithmetic expression P written in postfix notation.

1. Add aright parenthesis “)” at the end of P[This acts as a sentinel]2. Scan P from left to right and repeat step 3 and 4 for each element of P

until the sentinel “)” is encountered.3. If an operand is encountered, put it on STACK4. If an operator Θ is encountered, then

a) Remove the top two elements of STACKb) Evaluate A Θ Bc) Place the result of B back on STACK

[End of If structure]E[End of step 2 loop]

5. Set VALUE equal to the top element on STACK6. Exit

Transforming Infix Expression into Postfix Expression

• Suppose Q is an arithmetic expression written in infix notation. This algorithm finds the equivalent postfix expression P.POLISH(Q,P)

1. Push “(“ onto STACK, and add “)” to the end of Q2. Scan Q from left to right and repeat Step 3 to 6 for each element of Q until the STACK is empty3. If an operand is encountered, add it to P4. If a left parenthesis is encountered, push it onto STACK5. If operator Θ is encountered, then

a) Repeatedly pop from STACK and add to P each operator which has the same precedence as higher precedence than Θb) Add Θ operator to STACK

[End of if structure]6. If a right parenthesis is encountered, then

a) Repeatedly pop from STACK and add to P each operator until a left parenthesis is encountered.b) Remove the left parenthesis [Do not add the left parenthesis to P]

[End of if structure][End of step 2 loop]Exit

Quicksort

Quick sort is an algorithm of divide and conquer type. That is the problem of sorting a set is reduced to the problem of sorting two smaller sets.

Example• Suppose A is the following list of 12 numbers

44,33,11,55,77,90,40,60,99,22,88,66• The reduction step of quick sort algorithm finds the final position of one of the

numbers; in this we use the first number 44. Beginning with the last number, 66, scan the list from right to left, comparing each number with 44 and stopping at the first number less than 44. the number is 22. Interchange 44 and 22 to obtain the list.

22,33,11,55,77,90,40,60,99,44,88,66• Beginning with 22, next scan the list in opposite direction, from left to right,

comparing each number with 44 and stopping at the first number greater than 44. The number is 55. Interchange 44 and 55 to obtain the list.

22,33,11,44,77,90,40,60,99,55,88,66• Beginning this time with 55, now scanning the list in original direction that is from

right to left, until meeting the first number less than 44.It is 40. Interchange 44 and 40 to obtain the list.

22,33,11,40,77,90,44,60,99,55,88,66

22,33,11,40,44,90,77,60,99,55,88,66

Example• Beginning with 77, scan the list from right to left seeking a number less than 44.

We do not meet such number before meeting 44. This mean all the numbers have been scanned and compared with 44. All the numbers less tan 44 now form the sub list to the left of 44, and all numbers greater than 44 form the sub list to the right of 44 as shown below22,33,11,40, 44, 90,77,60,99,55,88,66

First sublist Second sublist

• Thus 44 is correctly placed in its final position, and the task of sorting the original list A has been reduced to the task of sorting each of the above sub list.

• The above reduction step is repeated with each sub list containing 2 or more elements. Since we can process only one sub list at a time, we must be able o keep track of some sub lists for future processing. This is accomplished by processing two stacks, called LOWER and UPPER, to temporarily old such sub list. That is the address of the first and last elements of each sub list, called its boundary values, are pushed onto the stacks LOWER and UPPER, respectively; and the reduction set is applied to a sub list only after its boundary values are removed from the stack.

Quick sort AlgorithmThis algorithm sorts an array A with N elements1. [Initialize] TOP=NULL2. [Push boundary values of A onto stack when A has 2 or more elements]

If N>1, then TOP=TOP+1, LOWER[1]=1 and UPPER[1]=N3. Repeat Step 4 to 7 while TOP!= NULL4. [Pop sub list from stack]

Set BEG=LOWER[TOP], END=UPPER[TOP]TOP=TOP-1

5. Call QUICK(A,N,BEG,END,LOC)6. [Push left sub list onto stacks when it has 2 or more elements]

If BEG<LOC-1 thenTOP=TOP+1, LOWER[TOP]=BEG, UPPER[TOP]=LOC-1

[End of If structure]7. [Push right sub list onto stacks when it has 2 or more elements]

If LOC+1 < END thenTOP=TOP+1, LOWER[TOP]= LOC+1, UPPER[TOP]= END

[End of If structure][End of Step 3 loop]

8. Exit

A is an array with N elements. Parameters BEG and END contain the boundary values of the sub list of A to which this procedure applies. LOC keeps track of the position of the first element A[BEG] of the sub list during the procedure. The local variables LEFT and RIGHT will contain the boundary values of the list of elements that have nor been scanned.QUICK(A,N,BEG,END,LOC)

1. [Initialize] Set LEFT=BEG, RIGHT= END and LOC=BEG2. [Scan from right to left]

a) Repeat while A[LOC]< A[RIGHT] and LOC!=RIGHTRIGHT=RIGHT-1

[End of Loop]b. If LOC=RIGHT, then Returnc. If A[LOC]>A[RIGHT], then

i. [Interchange A[LOC] and A[RIGHT], ] TEMP=A[LOC], A[LOC]=A[RIGHT] A[RIGHT]=TEMP

ii. Set LOC=RIGHTiii. Go to step 3[End of If Structure]

3. [Scan from left to right]a) Repeat while A[LEFT]< A[LOC] and LEFT!=LOC

LEFT=LEFT+1[End of Loop]

b. If LOC=LEFT, then Returnc. If A[LEFT]>A[LOC], then

i. [Interchange A[LEFT] and A[LOC], ] TEMP=A[LOC], A[LOC]=A[LEFT] A[LEFT]=TEMP

ii. Set LOC=LEFTiii. Go to step 2[End of If Structure]

Question

• Suppose S is the following list of alphabetic character:

S=DATASTRUCTURES

Use quick sort algorithm to find the final position of the first character D

CAADSTRUTTURES

Quicksort Analysis

• Assume that keys are random, uniformly distributed.

• What is best case running time?– Recursion:

1. Partition splits array in two sub-arrays of size n/2 2. Quicksort each sub-array

– Depth of recursion tree? O(log2n)

– Number of accesses in partition? O(n)

Quicksort Analysis

• Assume that keys are random, uniformly distributed.

• Best case running time: O(n log2n)

Quicksort Analysis

• Best case running time: O(n log2n)

• Worst case running time? O(n2)

Recursion• A function is said to be recursively defined, if a function

containing either a Call statement to itself or a Call statement to a second function that may eventually result in a Call statement back to the original function.

• A recursive function must have the following properties:

1. There must be certain criteria, called base criteria for which the function does not call itself.

2. Each time the function does call itself(directly or indirectly), the argument of the function must be closer to a base value.

Recursion

• In some problems, it may be natural to define the problem in terms of the problem itself.

• Recursion is useful for problems that can be represented by a simpler version of the same problem.

• Example: the factorial function6! = 6 * 5 * 4 * 3 * 2 * 1

We could write:6! = 6 * 5!

Example 1: factorial function

In general, we can express the factorial function as follows:

n! = n * (n-1)!

The factorial function is only defined for positive integers. So we should be a bit more precise:

if n<=1, then n! = 1

if n>1, then n! = n * (n-1)!

factorial function

The C++ equivalent of this definition:int fac(int numb){

if(numb<=1)

return 1;

else

return numb * fac(numb-1);

}

recursion means that a function calls itself

factorial function• Assume the number typed is 3, that is, numb=3. fac(3) :

int fac(int numb){if(numb<=1)

return 1;else return numb * fac(numb-1);

}

3 <= 1 ? No.fac(3) = 3 * fac(2)fac(2) :

2 <= 1 ? No.

fac(2) = 2 * fac(1)fac(1) :

1 <= 1 ? Yes.return 1

fac(2) = 2 * 1 = 2return fac(2)

fac(3) = 3 * 2 = 6return fac(3)

fac(3) has the value 6

factorial functionFor certain problems (such as the factorial function), a recursive solution often leads to short and elegant code. Compare the recursive solution with the iterative solution:

Iterative solution int fac(int numb){

int product=1; while(numb>1){

product *= numb; numb--;

} return product; }

Recursive solution

int fac(int numb){if(numb<=1)

return 1;else return numb*fac(numb-1);

}

Recursion

To trace recursion, recall that function calls operate as a stack – the new function is put on top of the caller

We have to pay a price for recursion:– calling a function consumes more time and memory than adjusting

a loop counter. – high performance applications (graphic action games, simulations

of nuclear explosions) hardly ever use recursion.

In less demanding applications recursion is an attractive alternative for iteration (for the right problems!)

Recursion

If we use iteration, we must be careful not to create an infinite loop by accident:

for(int incr=1; incr!=10;incr+=2) ...

int result = 1;while(result >0){ ... result++;}

RecursionSimilarly, if we use recursion we must be careful not to create an infinite chain of function calls:

int fac(int numb){

return numb * fac(numb-1);}

Or: int fac(int numb){

if (numb<=1) return 1; else return numb * fac(numb+1);}

No termination No termination conditioncondition

Recursion

We must always make sure that the recursion bottoms out:

• A recursive function must contain at least one non-recursive branch.

• The recursive calls must eventually lead to a non-recursive branch.

Recursion

• Recursion is one way to decompose a task into smaller subtasks. At least one of the subtasks is a smaller example of the same task.

• The smallest example of the same task has a non-recursive solution.

Example: The factorial functionn! = n * (n-1)! and 1! = 1

Example 2: Fibonacci numbers• Fibonacci numbers:

0, 1, 1, 2, 3, 5, 8, 13, 21, 34, ...

where each number is the sum of the preceding two.

• Recursive definition:– F(0) = 0;– F(1) = 1;– F(number) = F(number-1)+ F(number-2);

Example 3: Fibonacci numbers//Calculate Fibonacci numbers using recursive function.//A very inefficient way, but illustrates recursion well

int fib(int number){if (number == 0) return 0;if (number == 1) return 1;return (fib(number-1) + fib(number-2));

}

Trace a Fibonacci Number • Assume the input number is 4, that is, num=4:fib(4):

4 == 0 ? No; 4 == 1?No.fib(4) = fib(3) + fib(2)fib(3):

3 == 0 ? No; 3 == 1? No.fib(3) = fib(2) + fib(1) fib(2):

2 == 0? No; 2==1? No.fib(2) = fib(1)+fib(0)

fib(1): 1== 0 ? No; 1 == 1? Yes. fib(1) = 1;

return fib(1);

int fib(int num){

if (num == 0) return 0;if (num == 1) return 1;return

(fib(num-1)+fib(num-2));}

Trace a Fibonacci Number

fib(0): 0 == 0 ? Yes. fib(0) = 0; return fib(0);

fib(2) = 1 + 0 = 1; return fib(2);

fib(3) = 1 + fib(1) fib(1):

1 == 0 ? No; 1 == 1? Yes fib(1) = 1; return fib(1);

fib(3) = 1 + 1 = 2; return fib(3)

Trace a Fibonacci Numberfib(2):2 == 0 ? No; 2 == 1? No.fib(2) = fib(1) + fib(0)fib(1):

1== 0 ? No; 1 == 1? Yes. fib(1) = 1;

return fib(1); fib(0): 0 == 0 ? Yes. fib(0) = 0; return fib(0);

fib(2) = 1 + 0 = 1; return fib(2);

fib(4) = fib(3) + fib(2) = 2 + 1 = 3; return fib(4);

Fibonacci number w/o recursion//Calculate Fibonacci numbers iteratively//much more efficient than recursive solution

int fib(int n){int f[n+1]; f[0] = 0; f[1] = 1;

for (int i=2; i<= n; i++) f[i] = f[i-1] + f[i-2];return f[n];

}

Example 3: Binary Search

– Search for an element in an array• Sequential search• Binary search

– Binary search• Compare the search element with the middle

element of the array• If not equal, then apply binary search to half of

the array (if not empty) where the search element would be.

Binary Search with Recursion

// Searches an ordered array of integers using recursionint bsearchr(const int data[], // input: array int first, // input: lower bound int last, // input: upper bound int value // input: value to find )// output: index if found, otherwise return –1

{ int middle = (first + last) / 2; if (data[middle] == value) return middle; else if (first >= last) return -1; else if (value < data[middle]) return bsearchr(data, first, middle-1, value); else return bsearchr(data, middle+1, last, value);}

Binary Searchint main() {

const int array_size = 8;

int list[array_size]={1, 2, 3, 5, 7, 10, 14, 17};

int search_value;

cout << "Enter search value: ";

cin >> search_value;

cout << bsearchr(list,0,array_size-1,search_value)

<< endl;

return 0;

}

Binary Search w/o recursion// Searches an ordered array of integersint bsearch(const int data[], // input: array int size, // input: array size int value // input: value to find ){ // output: if found,return // index; otherwise, return -1

int first, last, upper; first = 0; last = size - 1;while (true) {

middle = (first + last) / 2; if (data[middle] == value) return middle; else if (first >= last) return -1; else if (value < data[middle]) last = middle - 1; else first = middle + 1; }}

Example 4: Towers of Hanoi

– Only one disc could be moved at a time– A larger disc must never be stacked above a

smaller one– One and only one extra needle could be used for

intermediate storage of discs

A B C

3

2

1

Towers of Hanoi

• From the moves necessary to transfer one, two, and three disks, we can find a recursive pattern - a pattern that uses information from one step to find the next step.

• If we want to know how many moves it will take to transfer 64 disks from post A to post C, we will first have to find the moves it takes to transfer 63 disks, 62 disks, and so on.

a) The initial state; b) move n - 1 disks from A to C

c) move one disk from A to B; d) move n - 1 disks from C to B

Towers of Hanoi• The recursive pattern can help us generate more numbers to find

an explicit (non-recursive) pattern. Here's how to find the number of moves needed to transfer larger numbers of disks from post A to post C, when M = the number of moves needed to transfer n-1 disks from post A to post C:

• for 1 disk it takes 1 move to transfer 1 disk from post A to post C;• for 2 disks, it will take 3 moves: 2M + 1 = 2(1) + 1 = 3 • for 3 disks, it will take 7 moves: 2M + 1 = 2(3) + 1 = 7• for 4 disks, it will take 15 moves: 2M + 1 = 2(7) + 1 = 15• for 5 disks, it will take 31 moves: 2M + 1 = 2(15) + 1 = 31• for 6 disks... ?

Towers of Hanoi

Number of Disks (n) Number of Moves

1 21 - 1 = 2 - 1 = 1 2 22 - 1 = 4 - 1 = 3 3 23 - 1 = 8 - 1 = 7 4 24 - 1 = 16 - 1 = 15 5 25 - 1 = 32 - 1 = 316 26 - 1 = 64 - 1 = 63

• So the formula for finding the number of steps it takes to transfer n disks from post A to post C is:

2 n - 1

Binomial coefficient

• Given a non-negative integer n and an integer k, the binomial coefficient is defined to be the natural number

• Example: