Lists, Stacks and Queues. 2 struct Node{ double data; Node* next; }; class List { public: List(); //...

102
Lists, Stacks and Queues
  • date post

    20-Dec-2015
  • Category

    Documents

  • view

    251
  • download

    2

Transcript of Lists, Stacks and Queues. 2 struct Node{ double data; Node* next; }; class List { public: List(); //...

Page 1: Lists, Stacks and Queues. 2 struct Node{ double data; Node* next; }; class List { public: List(); // constructor List(const List& list); // copy constructor.

Lists, Stacks and Queues

Page 2: Lists, Stacks and Queues. 2 struct Node{ double data; Node* next; }; class List { public: List(); // constructor List(const List& list); // copy constructor.

2

struct Node{ double data;Node* next;

};

class List {public:

List(); // constructorList(const List& list); // copy constructor~List(); // destructorList& operator=(const List& list); // assignment operator// plus other overloaded operators

bool empty() const; // boolean functionvoid add(double x); // add to the headvoid delete(); // delete the head and get the head elementdouble head() const; // get the head element

bool search(double x); // search for a given xvoid insert(double x); // insert x in a sorted listvoid delete(double x); // delete x in a sorted list

void addEnd(double x); // add to the endvoid deleteEnd(); // delete the end and get the end elementdouble end(); // get the element at the endvoid display() const; // outputint length() const; // count the number of elements

private:Node* head;

};

More complete list ADT

Page 3: Lists, Stacks and Queues. 2 struct Node{ double data; Node* next; }; class List { public: List(); // constructor List(const List& list); // copy constructor.

3

class List {public:

List(); // constructorList(const List& list); // copy constructor~List(); // destructor

bool empty() const; // boolean functiondouble head() const; // get the head elementvoid add(double x); // add to the headvoid delete(); // delete the head element

void display() const; // output

private:…

};

list ADT (a general list)

Or to define one function:

Double delete();

Which deletes and returns the head element.

Page 4: Lists, Stacks and Queues. 2 struct Node{ double data; Node* next; }; class List { public: List(); // constructor List(const List& list); // copy constructor.

4

class List {public:

List(); // constructorList(const List& list); // copy constructor~List(); // destructor

bool empty() const; // boolean functiondouble head(); const; // get the first elementvoid insert(double x); // insert x in a sorted listvoid delete(double x); // delete x in a sorted list

void display() const; // outputbool search(double x); // search for a given x

private:…

};

list ADT (a sorted list)

Page 5: Lists, Stacks and Queues. 2 struct Node{ double data; Node* next; }; class List { public: List(); // constructor List(const List& list); // copy constructor.

5

Implementation Static array Dynamic array Linked lists

with and without ‘dummy head’ tricks

Efficiency Insertion construction, composition Deletion destruction, decomposition Search application, usage

Implementation and Efficiency

Page 6: Lists, Stacks and Queues. 2 struct Node{ double data; Node* next; }; class List { public: List(); // constructor List(const List& list); // copy constructor.

6

Roughly ‘counting’ the number of operations, assuming all basis operations are of the same, unit one.

Efficiency: Algorithm Analysis

Page 7: Lists, Stacks and Queues. 2 struct Node{ double data; Node* next; }; class List { public: List(); // constructor List(const List& list); // copy constructor.

7

A Few Simple Rules Loops

at most the running time of the statements inside the for-loop (including tests) times the number of iterations.

O(N)

Nested loops

the running time of the statement multiplied by the product of the sizes of all the for-loops.

O(N2)

Page 8: Lists, Stacks and Queues. 2 struct Node{ double data; Node* next; }; class List { public: List(); // constructor List(const List& list); // copy constructor.

8

Consecutive statements These just add O(N) + O(N2) = O(N2)

Conditional: If S1 else S2 never more than the running time of the test plus the larger of

the running times of S1 and S2. O(1)

Page 9: Lists, Stacks and Queues. 2 struct Node{ double data; Node* next; }; class List { public: List(); // constructor List(const List& list); // copy constructor.

9

Our first example: search of an ordered array

Linear search and binary search Upper bound, lower bound and tight bound

Page 10: Lists, Stacks and Queues. 2 struct Node{ double data; Node* next; }; class List { public: List(); // constructor List(const List& list); // copy constructor.

10

O(N)

// Given an array of ‘size’ in increasing order, find ‘x’

int linearsearch(int* a[], int size,int x) {

int low=0, high=size-1;

for (int i=0; i<size;i++)

if (a[i]==x) return i;

return -1;

}

Linear search:

Page 11: Lists, Stacks and Queues. 2 struct Node{ double data; Node* next; }; class List { public: List(); // constructor List(const List& list); // copy constructor.

11

int bsearch(int* a[],int size,int x) {

int low=0, high=size-1;

while (low<=higt) {

int mid=(low+high)/2;

if (a[mid]<x)

low=mid+1;

else if (x<a[mid])

high=mid-1;

else return mid;

}

return -1

}

Iterative binary search:

Page 12: Lists, Stacks and Queues. 2 struct Node{ double data; Node* next; }; class List { public: List(); // constructor List(const List& list); // copy constructor.

12

int bsearch(int* a[],int size,int x) {

int low=0, high=size-1;

while (low<=higt) {

int mid=(low+high)/2;

if (a[mid]<x)

low=mid+1;

else if (x<a[mid])

high=mid-1;

else return mid;

}

return -1

}

Iterative binary search:

n=high-low n_i+1 <= n_i / 2 i.e. n_i <= (N-1)/2^{i-1} N stops at 1 or below there are at most 1+k iterations, where k is the smallest such that (N-1)/2^{k-1} <= 1 so k is at most 2+log(N-1) O(log N)

Page 13: Lists, Stacks and Queues. 2 struct Node{ double data; Node* next; }; class List { public: List(); // constructor List(const List& list); // copy constructor.

13

O(1)

T(N/2)

int bsearch(int* a[],int low, int high, int x) {

if (low>high) return -1;

else int mid=(low+high)/2;

if (x=a[mid]) return mid;

else if(a[mid]<x)

bsearch(a,mid+1,high,x);

else bsearch(a,low,mid-1);

}

O(1)

Recursive binary search:

1)2

()(

1)1(

N

TNT

T

Page 14: Lists, Stacks and Queues. 2 struct Node{ double data; Node* next; }; class List { public: List(); // constructor List(const List& list); // copy constructor.

14

With 2k = N (or asymptotically), k=log N, we have

Thus, the running time is O(log N)

NkNT log)(

kN

T

NT

NT

NTNT

k

)2

(

3)8

(

2)4

(

1)2

()(

Solving the recurrence:

Page 15: Lists, Stacks and Queues. 2 struct Node{ double data; Node* next; }; class List { public: List(); // constructor List(const List& list); // copy constructor.

15

Advantages and disadvantages of different implementations of a list

Static array

Dynamic array

Linked list

Insertion

Deletion

Search

Page 16: Lists, Stacks and Queues. 2 struct Node{ double data; Node* next; }; class List { public: List(); // constructor List(const List& list); // copy constructor.

16

Applications: Linked Implementation of Sparse Polynomials

Consider a polynomial of degree n Can be represented by a list

For a sparse polynomial this is not efficient

COMP152 16

myDegree 5

0 1 2 3 4 5 6 7 8 9

myCoeffs 5 7 0 -8 0 4 0 0 0 0

myDegree 99

0 1 2 3 4 5 6 7 8 9 … 95 96 97 98 99

myCoeffs 5 0 0 0 0 0 0 0 0 0 … 0 0 0 0 1

Page 17: Lists, Stacks and Queues. 2 struct Node{ double data; Node* next; }; class List { public: List(); // constructor List(const List& list); // copy constructor.

17

We could represent a polynomial by a list of ordered pairs{ (coef, exponent) … }

Fixed capacity of array still problematic Wasted space for sparse polynomial

COMP152 17

myDegree 5

0 1 2 3

myTerms 5 0 7 1 -8 3 4 5

myDegree 99

0 1

myTerms 5 0 1 99

Page 18: Lists, Stacks and Queues. 2 struct Node{ double data; Node* next; }; class List { public: List(); // constructor List(const List& list); // copy constructor.

18

Linked list of these ordered pairs provides an appropriate solution Now whether sparse or well populated, the polynomial is represented

efficiently Polynomial class (Polynomial.h)

Type parameter CoefType Term and Node are inner private classes for internal use and access only Used to create internal data structure of a linked node (for internal access only)

COMP152 18

0 0myTerms

5 0 7 1 -8 3 4 5

/

5myDegreedata

next

dummy/header/ sentinel

Page 19: Lists, Stacks and Queues. 2 struct Node{ double data; Node* next; }; class List { public: List(); // constructor List(const List& list); // copy constructor.

19

Stacks

Page 20: Lists, Stacks and Queues. 2 struct Node{ double data; Node* next; }; class List { public: List(); // constructor List(const List& list); // copy constructor.

20

Stack Overview

Stack ADT Basic operations of stack

Pushing, popping etc.

Implementations of stacks using array linked list

Page 21: Lists, Stacks and Queues. 2 struct Node{ double data; Node* next; }; class List { public: List(); // constructor List(const List& list); // copy constructor.

21

Stack

A stack is a list in which insertion and deletion take place at the same end This end is called top The other end is called bottom

Stacks are known as LIFO (Last In, First Out) lists. The last element inserted will be the first to be retrieved

Page 22: Lists, Stacks and Queues. 2 struct Node{ double data; Node* next; }; class List { public: List(); // constructor List(const List& list); // copy constructor.

22

Push and Pop

Primary operations: Push and Pop Push

Add an element to the top of the stack

Pop Remove the element at the top of the stack

top

empty stack

Atop

push an element

top

push another

A

Btop

pop

A

Page 23: Lists, Stacks and Queues. 2 struct Node{ double data; Node* next; }; class List { public: List(); // constructor List(const List& list); // copy constructor.

23

Implementation of Stacks

Any list implementation could be used to implement a stack Arrays (static: the size of stack is given initially) Linked lists (dynamic: never become full)

We will explore implementations based on arrays and linked list

Page 24: Lists, Stacks and Queues. 2 struct Node{ double data; Node* next; }; class List { public: List(); // constructor List(const List& list); // copy constructor.

24

class Stack {public:

Stack(); // constructorStack(const Stack& stack); // copy constructor~Stack(); // destructor

bool empty() const; double top() const; // keep the stack unchanged

void push(const double x); double pop(); // change the stack

// optionalvoid display() const; bool full() const;

private:…

};

Stack ADT

update,

‘logical’ constructor/destructor, composition/decomposition

‘physical’ constructor/destructor

Compare with List, see that it’s ‘operations’ that define the type!

‘stack’ is the same as our ‘unsorted’ list operating at the head

inspection, access

headElementaddHeaddeleteHead

Page 25: Lists, Stacks and Queues. 2 struct Node{ double data; Node* next; }; class List { public: List(); // constructor List(const List& list); // copy constructor.

25

Using Stack

int main() {Stack stack;stack.push(5.0);stack.push(6.5);stack.push(-3.0);stack.push(-8.0);stack.display();cout << "Top: " << stack.top() << endl;

stack.pop();cout << "Top: " << stack.top() << endl;while (!stack.empty()) stack.pop();stack.display();return 0;

}

result

Page 26: Lists, Stacks and Queues. 2 struct Node{ double data; Node* next; }; class List { public: List(); // constructor List(const List& list); // copy constructor.

26

struct Node{ public:

double data;Node* next;

};

class Stack {public:

Stack(); // constructorStack(const Stack& stack); // copy constructor~Stack(); // destructor

bool empty() const; double top() const; // keep the stack unchanged

void push(const double x); double pop(); // change the stack

bool full(); // unnecessary for linked lists void display() const;

private:Node* top;

};

Stack using linked lists

Page 27: Lists, Stacks and Queues. 2 struct Node{ double data; Node* next; }; class List { public: List(); // constructor List(const List& list); // copy constructor.

27

void List::addHead(int newdata){

Nodeptr newPtr = new Node;

newPtr->data = newdata;

newPtr->next = head;

head = newPtr;

}

void Stack::push(double x){

Node* newPtr = new Node;

newPtr->data = x;

newPtr->next = top;

top = newPtr;

}

From ‘addHead’ to ‘push’

Push (addHead), Pop (deleteHead)

Page 28: Lists, Stacks and Queues. 2 struct Node{ double data; Node* next; }; class List { public: List(); // constructor List(const List& list); // copy constructor.

28

Stack using arraysclass Stack {public:

Stack(int size = 10);Stack(const Stack& stack); ~Stack() { delete[] values; }

bool empty() { return (top == -1); }

double top();void push(const double x);double pop();

bool full() { return (top == size); }void display();

private:int size; // max stack size = size - 1int top; // current top of stackdouble* values; // element array

};

Page 29: Lists, Stacks and Queues. 2 struct Node{ double data; Node* next; }; class List { public: List(); // constructor List(const List& list); // copy constructor.

29

Attributes of Stack size: the max size of stack top: the index of the top element of stack values: point to an array which stores elements of stack

Operations of Stack empty: return true if stack is empty, return false otherwise full: return true if stack is full, return false otherwise top: return the element at the top of stack push: add an element to the top of stack pop: delete the element at the top of stack display: print all the data in the stack

Page 30: Lists, Stacks and Queues. 2 struct Node{ double data; Node* next; }; class List { public: List(); // constructor List(const List& list); // copy constructor.

30

Allocate a stack array of size. By default, size = 10.

Initially top is set to -1. It means the stack is empty. When the stack is full, top will have its maximum value, i.e.

size – 1.

Stack::Stack(int size /*= 10*/) {values = new double[size];top = -1;

maxTop = size - 1;}

Although the constructor dynamically allocates the stack array, the stack is still static. The size is fixed after the initialization.

Stack constructor

Page 31: Lists, Stacks and Queues. 2 struct Node{ double data; Node* next; }; class List { public: List(); // constructor List(const List& list); // copy constructor.

31

void push(const double x); Push an element onto the stack Note top always represents the index of the top

element. After pushing an element, increment top.

void Stack::push(const double x) {if (full()) // if stack is full, print error

cout << "Error: the stack is full." << endl;else

values[++top] = x;}

Page 32: Lists, Stacks and Queues. 2 struct Node{ double data; Node* next; }; class List { public: List(); // constructor List(const List& list); // copy constructor.

32

double pop() Pop and return the element at the top of the stack Don’t forgot to decrement top

double Stack::pop() {if (empty()) { //if stack is empty, print error

cout << "Error: the stack is empty." << endl;return -1;

}else {

return values[top--];}

}

Page 33: Lists, Stacks and Queues. 2 struct Node{ double data; Node* next; }; class List { public: List(); // constructor List(const List& list); // copy constructor.

33

double top() Return the top element of the stack Unlike pop, this function does not remove the top

element

double Stack::top() {if (empty()) {

cout << "Error: the stack is empty." << endl;return -1;

}else

return values[top];}

Page 34: Lists, Stacks and Queues. 2 struct Node{ double data; Node* next; }; class List { public: List(); // constructor List(const List& list); // copy constructor.

34

void print() Print all the elements

void Stack::print() {cout << "top -->";for (int i = top; i >= 0; i--)

cout << "\t|\t" << values[i] << "\t|" << endl;cout << "\t|---------------|" << endl;

}

Page 35: Lists, Stacks and Queues. 2 struct Node{ double data; Node* next; }; class List { public: List(); // constructor List(const List& list); // copy constructor.

35

A better variant:

COMP152 35

A better approach is to let position 0 be the bottom of the stack An integer to indicate the top of the stack (Stack.h)

[7] ?

[6] ?

[5] 77

[4] 121

[3] 64

[2] 234

[1] 51

[0] 64

[7] ?

[6] 95

[5] 77

[4] 121

[3] 64

[2] 234

[1] 51

[0] 29

[7] 80

[6] 95

[5] 77

[4] 121

[3] 64

[2] 234

[1] 51

[0] 29

[7] ?

[6] 95

[5] 77

[4] 121

[3] 64

[2] 234

[1] 51

[0] 29

Push 95 Push 80 Pop

top =

top =

top =

top =

Page 36: Lists, Stacks and Queues. 2 struct Node{ double data; Node* next; }; class List { public: List(); // constructor List(const List& list); // copy constructor.

36

Stack Application: base conversion

COMP152 36

Consider a program to do base conversion of a number (ten to two) 26 = (11010)2

It assumes existence of a Stack class to accomplish this Demonstrates push, pop, and top Push the remainder onto a stack and pop it

up one by one

Stack.h, Stack.cpp andBaseConversion.cpp

Can be written easily using recursion (do it yourself)

2 26

2 13 … 0

2 6 … 1

2 3 … 0

2 1 … 1

0 … 1

Page 37: Lists, Stacks and Queues. 2 struct Node{ double data; Node* next; }; class List { public: List(); // constructor List(const List& list); // copy constructor.

37

COMP152 37

Stack stack();

while (D is not zero) {

push the remainder of D

D D/2

}

while (not empty stack)

pop

Page 38: Lists, Stacks and Queues. 2 struct Node{ double data; Node* next; }; class List { public: List(); // constructor List(const List& list); // copy constructor.

38

COMP152 38

convert(D)

if D is zero, stop

else push(the remainder)

convert(D/2)

while (not empty stack)

pop

Page 39: Lists, Stacks and Queues. 2 struct Node{ double data; Node* next; }; class List { public: List(); // constructor List(const List& list); // copy constructor.

39

Stack Application: Balancing Symbols

To check that every right brace, bracket, and parentheses must correspond to its left counterpart e.g. [( )] is legal, but [( ] ) is illegal

How? Need to memorize Use a counter, several counters, each for a type of

parenthesis …

Page 40: Lists, Stacks and Queues. 2 struct Node{ double data; Node* next; }; class List { public: List(); // constructor List(const List& list); // copy constructor.

40

Balancing Symbols using a stack

Algorithm(1)   Make an empty stack.(2)   Read characters until end of file

i.    If the character is an opening symbol, push it onto the stackii.   If it is a closing symbol, then if the stack is empty, report an erroriii.  Otherwise, pop the stack. If the symbol popped is not the corresponding opening symbol, then report an error

(3)   At end of file, if the stack is not empty, report an error

(paren.cpp)

Page 41: Lists, Stacks and Queues. 2 struct Node{ double data; Node* next; }; class List { public: List(); // constructor List(const List& list); // copy constructor.

41

Stack Application: postfix, infix expressions and

calculator Evaluating Postfix expressions

a b c * + d e * f + g * + Operands are in a stack

Converting infix to postfix a+b*c+(d*e+f)*g a b c * + d e * f + g * + Operators are in a stack

Calculator Adding more operators …

Page 42: Lists, Stacks and Queues. 2 struct Node{ double data; Node* next; }; class List { public: List(); // constructor List(const List& list); // copy constructor.

42

Infix, prefix, and postfix

COMP152 42

Consider the arithmetic statement in the assignment statement:x = a * b + c

This is "infix" notation: the operators are between the operands

Compiler must generate machine instructions

1. LOAD a

2. MULT b

3. ADD c

4. STORE x

Page 43: Lists, Stacks and Queues. 2 struct Node{ double data; Node* next; }; class List { public: List(); // constructor List(const List& list); // copy constructor.

43

Examples

COMP152 43

Infix RPN (Postfix) Prefix

A + B A B + + A B

A * B + C A B * C + + * A B C

A * (B + C) A B C + * * A + B C

A - (B - (C - D)) A B C D--- -A-B-C D

A - B - C - D A B-C-D- ---A B C D

Prefix : Operators come before the

operands

Page 44: Lists, Stacks and Queues. 2 struct Node{ double data; Node* next; }; class List { public: List(); // constructor List(const List& list); // copy constructor.

44

RPN or Postfix Notation

COMP152 44

Reverse Polish Notation (RPN) = Postfix notation Most compilers convert an expression in infix notation to

postfix The operators are written after the operands

So “a * b + c” becomes “a b * c +” Easier for compiler to work on loading and operation of variables

Advantage: expressions can be written without parentheses

Page 45: Lists, Stacks and Queues. 2 struct Node{ double data; Node* next; }; class List { public: List(); // constructor List(const List& list); // copy constructor.

45

Evaluating RPN Expressions (Similar to Compiler Operations)

COMP152 45

Example:

2 3 4 + 5 6 - - * 2 3 4 + 5 6 - - * 2 7 5 6 - - * 2 7 5 6 - - * 2 7 -1 - * 2 7 -1 - * 2 8 * 2 8 * 16

Page 46: Lists, Stacks and Queues. 2 struct Node{ double data; Node* next; }; class List { public: List(); // constructor List(const List& list); // copy constructor.

46

COMP152 46

while (not the end of the expression) do {

get the current ‘token’

if it is operand, store it … a stack

if it is operator,

get back operands

Evaluate

store the result

move to the next

}

Use a Stack to store ‘operands’ a stack!

An expression is a list of ‘characters’ or more generally ‘tokens’ or ‘strings

Page 47: Lists, Stacks and Queues. 2 struct Node{ double data; Node* next; }; class List { public: List(); // constructor List(const List& list); // copy constructor.

47

COMP152 47

while (not the end of the expression) {

get the current ‘token’

if it is operand,

push;

else if it is operator,

pop;

pop;

evaluate;

push;

move to the next

}

Page 48: Lists, Stacks and Queues. 2 struct Node{ double data; Node* next; }; class List { public: List(); // constructor List(const List& list); // copy constructor.

48

COMP152 48

list expression

stack empty

while (notempty(list)) do {

c = head(list);

if (c == ‘operand’) push(c,stack)

else if (c == ‘operator)

operand2 = pop(stack);

operand1 = pop(stack);

res=evaluate(c,operand1,operand2);

push(res,stack);

list delete(list)

}

Further refine:

- operators: +, -, *, /

- operands: …

- evaluate: …

Page 49: Lists, Stacks and Queues. 2 struct Node{ double data; Node* next; }; class List { public: List(); // constructor List(const List& list); // copy constructor.

49

COMP152 49

List list(expression);

Stack stack();

while (list.notempty) do {

c = list.head();

if (c == ‘operand’) stack.push(c)

else if (c == ‘operator)

operand2 = stack.pop;

operand1 = stack.pop;

res=evaluate(c,operand1,operand2);

stack.push;

list.delete();

}

Further refine:

- operators: +, -, *, /

- operands: …

- evaluate: …

More object-oriented:

Page 50: Lists, Stacks and Queues. 2 struct Node{ double data; Node* next; }; class List { public: List(); // constructor List(const List& list); // copy constructor.

50

COMP152 50

2 4 * 9 5 + -

4 * 9 5 + -

* 9 5 + -

5 + -

+ -

(end of strings)

-

8

42

2

598

98

9 5 + -

148

-6

-6

Push 2 onto the stack

Value of expression is on top of the stack

Push 4 onto the stack

Pop 4 and 2 from the stack , multiply, and push the result 8 back

Push 9 onto the stack

Push 5 onto the stack

Pop 5 and 9 from the stack, add, and push the result 14 back

Pop 14 and 8 from the stack, subtract, and push the result -6 back

Page 51: Lists, Stacks and Queues. 2 struct Node{ double data; Node* next; }; class List { public: List(); // constructor List(const List& list); // copy constructor.

51

RPN Conversion

COMP152 51

1. Given a fully parenthesized infix expression

2. Replace each right parenthesis by the corresponding operator

3. Erase all left parentheses

A * (B + C)

(A (B C + * A B C + *

(A * (B + C) )A * B + C

((A B * C + A B * C +

((A * B) + C)

Page 52: Lists, Stacks and Queues. 2 struct Node{ double data; Node* next; }; class List { public: List(); // constructor List(const List& list); // copy constructor.

52

COMP152 52

while (not end of expression)

c = the current ‘token’if c is ‘operator’

store it somewhere … (a stack!)

else if c is ‘operand’,

display it (or store them in a new expression),

A stack for operators, not operands!

Page 53: Lists, Stacks and Queues. 2 struct Node{ double data; Node* next; }; class List { public: List(); // constructor List(const List& list); // copy constructor.

53

COMP152 53

while (not end of expression) {c = the current ‘token’

If c is ‘(‘

else if c is ‘)’

else if c is ‘operator’

push

else if c is ‘operand’,

pop

}

while (not end of the stack) {

pop

}

Page 54: Lists, Stacks and Queues. 2 struct Node{ double data; Node* next; }; class List { public: List(); // constructor List(const List& list); // copy constructor.

54

COMP152 54

while (not end of expression)c = the current ‘token’

If c is ‘(’push

else if c is ‘)’

while (the top is not ‘(‘ )

pop and display

else if c is ‘operator’,

while (the top has higher priority than c,

and is not ‘(‘ )

pop and display

push

else if c is ‘operand’

pop and display

while (notempty stack)

pop an display

postfix.cpp

Page 55: Lists, Stacks and Queues. 2 struct Node{ double data; Node* next; }; class List { public: List(); // constructor List(const List& list); // copy constructor.

55

Stack Application: function calls and recursion

Take the example of factorial! And run it.

#include <iostream>using namespace std;

int fac(int n){int product;if(n <= 1) product = 1;else product = n * fac(n-1);return product;

}

void main(){int number;cout << "Enter a positive integer : " << endl;;cin >> number;cout << fac(number) << endl;

}

Page 56: Lists, Stacks and Queues. 2 struct Node{ double data; Node* next; }; class List { public: List(); // constructor List(const List& list); // copy constructor.

56

Take the example of factorial! And run it.

#include <iostream>using namespace std;

int fac(int n){int product;if(n <= 1) product = 1;else product = n * fac(n-1);return product;

}

void main(){int number;cout << "Enter a positive integer : " << endl;;cin >> number;cout << fac(number) << endl;

}

Page 57: Lists, Stacks and Queues. 2 struct Node{ double data; Node* next; }; class List { public: List(); // constructor List(const List& list); // copy constructor.

57

Assume the number typed is 3. fac(3): has the final returned value 6

3<=1 ? No.

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

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

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

fac(1):1<=1 ? Yes.return 1

Tracing the program …

Page 58: Lists, Stacks and Queues. 2 struct Node{ double data; Node* next; }; class List { public: List(); // constructor List(const List& list); // copy constructor.

58

fac(3) prod3=3*fac(2)

prod2=2*fac(1)fac(2)

fac(1) prod1=1

Call is to ‘push’ and return is to ‘pop’!

top

Page 59: Lists, Stacks and Queues. 2 struct Node{ double data; Node* next; }; class List { public: List(); // constructor List(const List& list); // copy constructor.

59

COMP152 59

Stack stack();

while (D is not zero) {

push the remainder of D

D D/2

}

while (not empty stack)

pop

Let the system do the ‘stack’ for you!

convert(D)

if D is zero, stop

else push(the remainder)

convert(D/2)

while (not empty stack)

pop and display

convert(D)

if D is zero, stop

else convert(D/2)

display the remainder of D

Page 60: Lists, Stacks and Queues. 2 struct Node{ double data; Node* next; }; class List { public: List(); // constructor List(const List& list); // copy constructor.

60

Static and dynamic objects

‘static variables’ are from a Stack ‘dynamic variables’ are from a heap (seen

later …)

Page 61: Lists, Stacks and Queues. 2 struct Node{ double data; Node* next; }; class List { public: List(); // constructor List(const List& list); // copy constructor.

61

Array versus linked list implementations

push, pop, top are all constant-time operations in both array and linked list implementation For array implementation, the operations are

performed in very fast constant time

Page 62: Lists, Stacks and Queues. 2 struct Node{ double data; Node* next; }; class List { public: List(); // constructor List(const List& list); // copy constructor.

62

Queues

COMP152 62

A queue is a waiting line – seen in daily life A line of people waiting for a bank teller A line of cars at a toll both "This is the captain, we're 5th in line for takeoff"

Page 63: Lists, Stacks and Queues. 2 struct Node{ double data; Node* next; }; class List { public: List(); // constructor List(const List& list); // copy constructor.

63

Queue Overview

Queue ADT Basic operations of queue

Enqueuing, dequeuing etc.

Implementation of queue Linked list Array

Page 64: Lists, Stacks and Queues. 2 struct Node{ double data; Node* next; }; class List { public: List(); // constructor List(const List& list); // copy constructor.

64

Queue

A queue is also a list. However, insertion is done at one end, while deletion is performed at the other end.

It is “First In, First Out (FIFO)” order. Like customers standing in a check-out line in a

store, the first customer in is the first customer served.

Page 65: Lists, Stacks and Queues. 2 struct Node{ double data; Node* next; }; class List { public: List(); // constructor List(const List& list); // copy constructor.

65

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

Page 66: Lists, Stacks and Queues. 2 struct Node{ double data; Node* next; }; class List { public: List(); // constructor List(const List& list); // copy constructor.

66

Implementation of Queue

Just as stacks can be implemented as arrays or linked lists, so with queues.

Dynamic queues have the same advantages over static queues as dynamic stacks have over static stacks

Page 67: Lists, Stacks and Queues. 2 struct Node{ double data; Node* next; }; class List { public: List(); // constructor List(const List& list); // copy constructor.

67

class Queue {public:

Queue();Queue(const Queue& queue);~Queue();

bool empty();double front(); // optional: front inspection (no queue change)void enqueue(double x);double dequeue();

// optionalvoid display(void);bool full();

private:…

};

Queue ADT

‘physical’ constructor/destructor

‘logical’ constructor/destructor

Page 68: Lists, Stacks and Queues. 2 struct Node{ double data; Node* next; }; class List { public: List(); // constructor List(const List& list); // copy constructor.

68

Using Queueint main(void) {

Queue queue;cout << "Enqueue 5 items." << endl;for (int x = 0; x < 5; x++)

queue.enqueue(x);cout << "Now attempting to enqueue again..." << endl;queue.enqueue(5);queue.print();double value;value=queue.dequeue();cout << "Retrieved element = " << value << endl;queue.print();queue.enqueue(7);queue.print();return 0;

}

Page 69: Lists, Stacks and Queues. 2 struct Node{ double data; Node* next; }; class List { public: List(); // constructor List(const List& list); // copy constructor.

69

Struct Node {double data;Node* next;

}

class Queue {public:

Queue();Queue(const Queue& queue);~Queue();

bool empty();void enqueue(double x);double dequeue();

// bool full(); // optionalvoid print(void);

private:Node* front; // pointer to front nodeNode* rear; // pointer to last nodeint counter; // number of elements

};

Queue using linked lists

Page 70: Lists, Stacks and Queues. 2 struct Node{ double data; Node* next; }; class List { public: List(); // constructor List(const List& list); // copy constructor.

70

class Queue {public:

Queue() { // constructorfront = rear = NULL;counter = 0;

}~Queue() { // destructor

double value;while (!empty()) dequeue(value);

}bool empty() {

if (counter) return false;else return true;

}void enqueue(double x);double dequeue();

// bool full() {return false;};void print(void);

private:Node* front; // pointer to front nodeNode* rear; // pointer to last nodeint counter; // number of elements, not compulsary

};

Implementation of some online member functions …

Page 71: Lists, Stacks and Queues. 2 struct Node{ double data; Node* next; }; class List { public: List(); // constructor List(const List& list); // copy constructor.

71

Enqueue (addEnd)void Queue::enqueue(double x) {

Node* newNode = new Node;newNode->data = x;newNode->next = NULL;

if (empty()) {front = newNode;

}else {

rear->next = newNode;}

rear = newNode;counter++;

}

8

rear

rear

newNode

5

58

Page 72: Lists, Stacks and Queues. 2 struct Node{ double data; Node* next; }; class List { public: List(); // constructor List(const List& list); // copy constructor.

72

Dequeue (deleteHead)double Queue::dequeue() {

double x;if (empty()) {

cout << "Error: the queue is empty." << endl;exit(1); // return false;

}else {

x = front->data;Node* nextNode = front->next;delete front;front = nextNode;counter--;

}return x;

}

front

583

8 5

front

Page 73: Lists, Stacks and Queues. 2 struct Node{ double data; Node* next; }; class List { public: List(); // constructor List(const List& list); // copy constructor.

73

Printing all the elements

void Queue::print() {cout << "front -->";Node* currNode = front;for (int i = 0; i < counter; i++) {

if (i == 0) cout << "\t";else cout << "\t\t"; cout << currNode->data;if (i != counter - 1)

cout << endl;else

cout << "\t<-- rear" << endl;currNode = currNode->next;

}}

Page 74: Lists, Stacks and Queues. 2 struct Node{ double data; Node* next; }; class List { public: List(); // constructor List(const List& list); // copy constructor.

74

Queue using Arrays There are several different algorithms to

implement Enqueue and Dequeue Naïve way

When enqueuing, the front index is always fixed and the rear index moves forward in the array.

front

rear

Enqueue(3)

3

front

rear

Enqueue(6)

3 6

front

rear

Enqueue(9)

3 6 9

Page 75: Lists, Stacks and Queues. 2 struct Node{ double data; Node* next; }; class List { public: List(); // constructor List(const List& list); // copy constructor.

75

Naïve way (cont’d) When dequeuing, the front index is fixed, and the

element at the front the queue is removed. Move all the elements after it by one position. (Inefficient!!!)

Dequeue()

front

rear

6 9

Dequeue() Dequeue()

front

rear

9

rear = -1

front

Page 76: Lists, Stacks and Queues. 2 struct Node{ double data; Node* next; }; class List { public: List(); // constructor List(const List& list); // copy constructor.

76

A better way When enqueued, the rear index moves forward. When dequeued, the front index also moves forward

by one element

XXXXOOOOO (rear) OXXXXOOOO (after 1 dequeue, and 1 enqueue)OOXXXXXOO (after another dequeue, and 2 enqueues)OOOOXXXXX (after 2 more dequeues, and 2 enqueues)

(front)

The problem here is that the rear index cannot move beyond the last element in the array.

Page 77: Lists, Stacks and Queues. 2 struct Node{ double data; Node* next; }; class List { public: List(); // constructor List(const List& list); // copy constructor.

77

Using Circular Arrays

Using a circular array When an element moves past the end of a circular

array, it wraps around to the beginning, e.g. OOOOO7963 4OOOO7963 (after Enqueue(4))

How to detect an empty or full queue, using a circular array algorithm? Use a counter of the number of elements in the queue.

Page 78: Lists, Stacks and Queues. 2 struct Node{ double data; Node* next; }; class List { public: List(); // constructor List(const List& list); // copy constructor.

78

class Queue {public:

Queue(int size = 10); // constructorQueue(const Queue& queue); // not necessary!

~Queue() { delete[] values; } // destructor

bool empty(void);void enqueue(double x); // or bool enqueue();double dequeue();

bool full();void print(void);

private:int front; // front indexint rear; // rear indexint counter; // number of elementsint maxSize; // size of array queuedouble* values; // element array

};

full() is not essential, can be embedded

Page 79: Lists, Stacks and Queues. 2 struct Node{ double data; Node* next; }; class List { public: List(); // constructor List(const List& list); // copy constructor.

79

Attributes of Queue front/rear: front/rear index counter: number of elements in the queue maxSize: capacity of the queue values: point to an array which stores elements of the queue

Operations of Queue empty: return true if queue is empty, return false otherwise full: return true if queue is full, return false otherwise enqueue: add an element to the rear of queue dequeue: delete the element at the front of queue print: print all the data

Page 80: Lists, Stacks and Queues. 2 struct Node{ double data; Node* next; }; class List { public: List(); // constructor List(const List& list); // copy constructor.

80

Queue constructor

Queue(int size = 10) Allocate a queue array of size. By default, size = 10. front is set to 0, pointing to the first element of the

array rear is set to -1. The queue is empty initially.

Queue::Queue(int size /* = 10 */) {values = new double[size];maxSize = size;front = 0;rear = -1;counter = 0;

}

Page 81: Lists, Stacks and Queues. 2 struct Node{ double data; Node* next; }; class List { public: List(); // constructor List(const List& list); // copy constructor.

81

Empty & Full Since we keep track of the number of elements

that are actually in the queue: counter, it is easy to check if the queue is empty or full.

bool Queue::empty() {if (counter==0) return true;else return false;

}bool Queue::full() {

if (counter < maxSize) return false;else return true;

}

Page 82: Lists, Stacks and Queues. 2 struct Node{ double data; Node* next; }; class List { public: List(); // constructor List(const List& list); // copy constructor.

82

Enqueue

void Queue::enqueue(double x) {if (full()) {

cout << "Error: the queue is full." << endl;exit(1); // return false;

}else {

// calculate the new rear position (circular)rear = (rear + 1) % maxSize; // insert new itemvalues[rear] = x;// update countercounter++;// return true;

}}

Or ‘bool’ if you want

Page 83: Lists, Stacks and Queues. 2 struct Node{ double data; Node* next; }; class List { public: List(); // constructor List(const List& list); // copy constructor.

83

Dequeue

double Queue::dequeue() {double x;if (empty()) {

cout << "Error: the queue is empty." << endl;exit(1); // return false;

}else {

// retrieve the front itemx = values[front];// move front front = (front + 1) % maxSize;// update countercounter--;// return true;

}return x;

}

Page 84: Lists, Stacks and Queues. 2 struct Node{ double data; Node* next; }; class List { public: List(); // constructor List(const List& list); // copy constructor.

84

Printing the elements

void Queue::print() {cout << "front -->";for (int i = 0; i < counter; i++) {

if (i == 0) cout << "\t";else cout << "\t\t"; cout << values[(front + i) % maxSize];if (i != counter - 1)

cout << endl;else

cout << "\t<-- rear" << endl;}

}

Page 85: Lists, Stacks and Queues. 2 struct Node{ double data; Node* next; }; class List { public: List(); // constructor List(const List& list); // copy constructor.

85

Using Queueint main(void) {

Queue queue;cout << "Enqueue 5 items." << endl;for (int x = 0; x < 5; x++)

queue.enqueue(x);cout << "Now attempting to enqueue again..." << endl;queue.enqueue(5);queue.print();double value;value=queue.dequeue();cout << "Retrieved element = " << value << endl;queue.print();queue.enqueue(7);queue.print();return 0;

}

Page 86: Lists, Stacks and Queues. 2 struct Node{ double data; Node* next; }; class List { public: List(); // constructor List(const List& list); // copy constructor.

86

Results

Queue implemented using linked list will be never full!

based on array based on linked list

Page 87: Lists, Stacks and Queues. 2 struct Node{ double data; Node* next; }; class List { public: List(); // constructor List(const List& list); // copy constructor.

87

Queue applications

When jobs are sent to a printer, in order of arrival, a queue.

Customers at ticket counters …

Page 88: Lists, Stacks and Queues. 2 struct Node{ double data; Node* next; }; class List { public: List(); // constructor List(const List& list); // copy constructor.

88

Queue application: Counting Sort

Assume N integers are to be sorted, each is in the range 1 to M. Define an array B[1..M], initialize all to 0 O(M) Scan through the input list A[i], insert A[i] into B[A[i]] O(N) Scan B once, read out the nonzero integers O(M)

Total time: O(M + N) if M is O(N), then total time is O(N) Can be bad if range is very big, e.g. M=O(N2)

N=7, M = 9,

Want to sort 8 1 9 5 2 6 3

1 2 5 8 9

Output: 1 2 3 5 6 8 9

3 6

Page 89: Lists, Stacks and Queues. 2 struct Node{ double data; Node* next; }; class List { public: List(); // constructor List(const List& list); // copy constructor.

89

What if we have duplicates? B is an array of pointers. Each position in the array has 2 pointers: head

and tail. Tail points to the end of a linked list, and head points to the beginning.

A[j] is inserted at the end of the list B[A[j]] Again, Array B is sequentially traversed and

each nonempty list is printed out. Time: O(M + N)

Page 90: Lists, Stacks and Queues. 2 struct Node{ double data; Node* next; }; class List { public: List(); // constructor List(const List& list); // copy constructor.

90

M = 9,

Wish to sort 8 5 1 5 9 5 6 2 7

1 2 5 6 7 8 9

Output: 1 2 5 5 5 6 7 8 9

5

5

Page 91: Lists, Stacks and Queues. 2 struct Node{ double data; Node* next; }; class List { public: List(); // constructor List(const List& list); // copy constructor.

91

Queue Application: Bin (or Bucket) Sort (generalization of

counting sort) The nodes are placed into bins, each bin contains nodes with the

same score Then we combine the bins to create a sorted chain Note that it does not change the relative order of nodes that have

the same score, the so-called stable sort.

COMP152 91

Page 92: Lists, Stacks and Queues. 2 struct Node{ double data; Node* next; }; class List { public: List(); // constructor List(const List& list); // copy constructor.

92

Number of Steps in binsort

m integers, r array size

Sort m integers For example, sort m=1,000 integers in the range of 0 to r=106

We use binsort with range r: Initialization of array takes r steps; putting items into the array takes m steps; and reading out from the array takes another m+r steps The total sort complexity is then (2m + 2r) , which can be much

larger than m if r is large

COMP152 92

Page 93: Lists, Stacks and Queues. 2 struct Node{ double data; Node* next; }; class List { public: List(); // constructor List(const List& list); // copy constructor.

93

Queue application: Radix Sort

Extra information: every integer can be represented by at most k digits d1d2…dk where di are digits in base r

d1: most significant digit

dk: least significant digit

Page 94: Lists, Stacks and Queues. 2 struct Node{ double data; Node* next; }; class List { public: List(); // constructor List(const List& list); // copy constructor.

94

Radix Sort

Algorithm sort by the least significant digit first (counting sort)

=> Numbers with the same digit go to same bin reorder all the numbers: the numbers in bin 0

precede the numbers in bin 1, which precede the numbers in bin 2, and so on

sort by the next least significant digit continue this process until the numbers have been

sorted on all k digits

Page 95: Lists, Stacks and Queues. 2 struct Node{ double data; Node* next; }; class List { public: List(); // constructor List(const List& list); // copy constructor.

95

Radix Sort

Least-significant-digit-first

Example: 275, 087, 426, 061, 509, 170, 677, 503

170 061 503 275 426 087 677 509

Page 96: Lists, Stacks and Queues. 2 struct Node{ double data; Node* next; }; class List { public: List(); // constructor List(const List& list); // copy constructor.

96

170 061 503 275 426 087 677 509

503 509 426 061 170 275 677 087

061 087 170 275 426 503 509 677

Page 97: Lists, Stacks and Queues. 2 struct Node{ double data; Node* next; }; class List { public: List(); // constructor List(const List& list); // copy constructor.

97

Radix Sort Does it work?

Clearly, if the most significant digit of a and b are different and a < b, then finally a comes before b

If the most significant digit of a and b are the same, and the second most significant digit of b is less than that of a, then b comes before a.

Page 98: Lists, Stacks and Queues. 2 struct Node{ double data; Node* next; }; class List { public: List(); // constructor List(const List& list); // copy constructor.

98

Radix(A[],n,d)

// an array of queues as bins

Queue Q[9]();

k=0;

D=1;

while (k <= d)

get k-th digit t of A[i]

enqueue(A[i],Q[t])

k=k+1;

// out put Q

p=0;

j=0;

While (p<=9)

While (not empty Q[j])

A[j]=dequeue(Q(p));

j=j+1;

p=p+1;

Page 99: Lists, Stacks and Queues. 2 struct Node{ double data; Node* next; }; class List { public: List(); // constructor List(const List& list); // copy constructor.

99

COMP152 99

Finding digit Di From Key We want to find the ith digit in our key A

A = DdDd-1.. Di…D2D1

mod and div are integer operators

Let D = 10i

Then Di = (A mod D) div (D/10)

Get Digit

Example. A=30487 we want D3

i =3, D = 1000A mod 1000 = 487 (first)487 div (D/10) (second)487 div (100) = 4 result!

Page 100: Lists, Stacks and Queues. 2 struct Node{ double data; Node* next; }; class List { public: List(); // constructor List(const List& list); // copy constructor.

100

// base 10

// d times of counting sort

// re-order back to original array

// scan A[i], put into correct slot

// FIFO

A=input array, n=|numbers to be sorted|,

d=# of digits, k=the digit being sorted, j=array index

Page 101: Lists, Stacks and Queues. 2 struct Node{ double data; Node* next; }; class List { public: List(); // constructor List(const List& list); // copy constructor.

101

Radix Sort

Increasing the base r decreases the number of passes Running time

k passes over the numbers (i.e. k counting sorts, with range being 0..r)

each pass takes 2N total: O(2Nk)=O(Nk) r and k are constants: O(N)

Note: radix sort is not based on comparisons; the values are used as

array indices If all N input values are distinct, then k = (log N) (e.g., in

binary digits, to represent 8 different numbers, we need at least 3 digits). Thus the running time of Radix Sort also become (N log N).

Page 102: Lists, Stacks and Queues. 2 struct Node{ double data; Node* next; }; class List { public: List(); // constructor List(const List& list); // copy constructor.

102

Radix Sort

Example 2: sorting cards 2 digits for each card: d1d2

d1 = : base 4

d2 = A, 2, 3, ...J, Q, K: base 13 A 2 3 ... J Q K

2 2 5 K