chapter 3: lists, stacks, and queues

26
Chapter 3: Lists, Stacks, and Q •Abstract Data Types •Lists and Sorted Lists CS 340 Page 1 •Stacks and Stack Application •Queues and Queue Applicatio

Upload: maj

Post on 24-Feb-2016

64 views

Category:

Documents


0 download

DESCRIPTION

Chapter 3: Lists, Stacks, and Queues. Abstract Data Types. Lists and Sorted Lists. Stacks and Stack Applications. Queues and Queue Applications. CS 340. Page 34. Abstract Data Types. An ADT is a set of operations upon a set of data. Implementation details are not specified in an ADT. - PowerPoint PPT Presentation

TRANSCRIPT

Page 1: Chapter 3: Lists, Stacks, and Queues

Chapter 3: Lists, Stacks, and Queues• Abstract Data Types• Lists and Sorted Lists

CS 340 Page 1

• Stacks and Stack Applications• Queues and Queue Applications

Page 2: Chapter 3: Lists, Stacks, and Queues

CS 340 Page 2

Abstract Data TypesAn ADT is a set of operations upon a set of

data. Implementation details are not specified

in an ADT. The program designer determines the

operations that are needed and the specific data that will be used in the implementation.

The implementation of the ADT should be easy to modify, and such modifications should be transparent to any code deploying the ADT.

Page 3: Chapter 3: Lists, Stacks, and Queues

CS 340 Page 3

ADT #1: The ListA list is a finite ordered collection of items

of the same type.Common list operations include: Emptying the entire list Determining whether the list is empty Determining the size of the list Determining the location of a particular

list element Determining the value of an element at

a particular location in the list Inserting a new list element at a

particular location Removing a particular element from the

list Outputting the entire list

Page 4: Chapter 3: Lists, Stacks, and Queues

CS 340 Page 4

An Array Implementation’s PerformanceList Implementation Option: Array

a1

a2

a3

:an-2

an-1

an

??:?

n

Problems with the array implementation:– Data movement really slows down

insertions to and removals from the list

– The maximum list size must be specified

Emptying the list O(1)Determining if the list is empty O(1)

Determining the size of the list O(1)Determining the location of a particular element O(n)Determining the value of an element in a particular location O(1)Inserting a new element into a particular location O(n)

Removing a particular element O(n)Outputting the list O(n)

Page 5: Chapter 3: Lists, Stacks, and Queues

CS 340 Page 5

A Linked List Implementation’s Performance

List Implementation Option: Linked List

Problems with the linked list implementation:– Pointers consume memory not needed

with arrays– Lack of indexing necessitates repeated

list traversals (e.g., binary search is impossible)

a1

a2

a3

:

an-2

an-1

an

Emptying the list O(n)Determining if the list is empty O(1)

Determining the size of the list O(n)Determining the location of a particular element O(n)Determining the value of an element in a particular location O(n)Inserting a new element into a particular location O(1)

Removing a particular element O(1)Outputting the list O(n)

Page 6: Chapter 3: Lists, Stacks, and Queues

CS 340 Page 6

#ifndef LIST_H#include <cstdlib>template <class Etype> class list{ protected: struct node { Etype element; node *next; node(Etype e = 0, node *n = NULL) : element(e), next(n) {} }; node *head; node *current; void deleteList();

public: list(): head(new node), current(head) {} virtual ~list() { deleteList(); } const list& operator = (list &value); const list& operator ++ (); bool operator ! () const; const Etype& operator () () const; bool isEmpty() const { return (head->next == NULL); } virtual bool find(const Etype &x); virtual bool findPrevious(const Etype &x); void first() { if (head->next != NULL) current = head->next; } void header() { current = head; } bool remove(const Etype &x); virtual void insert(const Etype &x); virtual void insertAsFirstElement(const Etype &x);};

Linked List Implementation in Visual C++

Class Template

Structure

Structure Constructor

Class Constructor

Class Destructor

Virtual Function: Derived

classes may have their

own version of this

function

ConstantReturn: Value

returned is treated as a

constant

Constant Modifier: This operator accesses but doesn’t

modify

In-Line Code

Page 7: Chapter 3: Lists, Stacks, and Queues

CS 340 Page 7

// Member function to free all memory associated with the linked list.template <class Etype> void list<Etype>:: deleteList(){ node *p = head->next; node *temp; while (p != NULL) { temp = p->next; delete p; p = temp; } delete head;}

// Assignment operator: duplicates parameterized linked list.template <class Etype> inline const list<Etype>& list<Etype>:: operator = (list &value){ if (this == &value) return *this; deleteList(); current = head = new node; for (value.first(); !value; ++value) { current->next = new node(value(), current->next); current = current->next; } current->next = NULL; first(); value.first(); return *this;}

In-Line Function: Prompts the compiler to generate code inline

instead of laying it down once and calling it through the usual

mechanisms, improving performance for functions that do

little but are called often

Page 8: Chapter 3: Lists, Stacks, and Queues

CS 340 Page 8

// Increment operator: moves current pointer to next node (if possible).template <class Etype> inline const list<Etype>& list<Etype>:: operator ++ (){ if (current != NULL) current = current->next; return *this;}

// Logical “not” operator: indicates whether current pointer is non-NULL.template <class Etype> inline bool list<Etype>:: operator ! () const{ return (current != NULL);}

// Parenthetical operator: returns value of current node (or head node if current is NULL).template <class Etype> inline const Etype& list<Etype>:: operator () () const{ if (current != NULL) return current->element; else return head->element;}

Page 9: Chapter 3: Lists, Stacks, and Queues

CS 340 Page 9

// Member function to determine whether parameterized element is in list.template <class Etype> bool list<Etype>:: find(const Etype &x){ node *p; for (p = head->next; p != NULL; p = p->next) { if (p->element == x) { current = p; return true; } } return false;}

// Member function to locate predecessor of parameterized value in list.template <class Etype> bool list<Etype>:: findPrevious(const Etype &x){

node *p;for (p = head; p->next != NULL; p = p->next){ if (p->next->element == x) { current = p; return true; }}return false;

}

Page 10: Chapter 3: Lists, Stacks, and Queues

CS 340 Page 10

// Member function to remove first occurrence of parameterized value from list.template <class Etype> bool list<Etype>:: remove(const Etype &x){

node *cellToDelete;if (findPrevious(x)){ cellToDelete = current->next; current->next = cellToDelete->next; delete cellToDelete; return true;}return false;

}

// Member function to insert parameterized value after current node in list.template <class Etype> void list<Etype>:: insert(const Etype &x){

node *p = new node(x, current->next);if (p != NULL){ current->next = p; current = current->next;}

}

// Member function to insert parameterized value as new head element in list.template <class Etype> void list<Etype>:: insertAsFirstElement(const Etype &x){

header();insert(x);

}

#define LIST_H#endif

Page 11: Chapter 3: Lists, Stacks, and Queues

CS 340 Page 11

#include "List.h"#include <iostream>using namespace std;void printList(list<int> &lst);// The main function generates a couple of integer lists// to test the functionality of the linked list class.void main(){ list<int> lst1, lst2; cout << "(This should be empty)" << endl; printList(lst1); for (int i = 1; i <= 5; i++) lst1.insertAsFirstElement(i); cout << "(This should be 5 4 3 2 1)" << endl; printList(lst1); for (int i = 4; i <= 6; i++) if (lst1.find(i)) cout << "Found " << lst1() << endl; else cout << i << " not found" << endl; lst2 = lst1; cout << "(This should be 5 4 3 2 1)" << endl; printList(lst2); lst2.remove(3); cout << "(This should be 5 4 2 1)" << endl; printList(lst2); cout << "(but this should still be 5 4 3 2 1)" << endl; printList(lst1);}

A Test Driver For The Linked List Implementation

Page 12: Chapter 3: Lists, Stacks, and Queues

CS 340 Page 12

// The printList function outputs the contents// of the linked list, starting at the head.void printList(list<int> &lst){ if (lst.isEmpty()) cout << "Empty list." << endl; else for (lst.first(); !lst; ++lst) cout << lst() << endl;}

Page 13: Chapter 3: Lists, Stacks, and Queues

CS 340 Page 13

Inheritance: The sortedList ClassIf Etype values can be sorted, then the list class can be modified to accommodate this sorting.This can be easily accomplished by deriving a subclass of list, and overriding the two insertion functions insert and insertAsFirstElement.

#include "List.h"template <class Etype> class sortedList: public list<Etype>{ public: virtual void insert(const Etype &x); virtual void insertAsFirstElement(const Etype &x) { insert(x); }}

// This member function inserts the parameterized// value and preserves the sorted nature of the list.template <class Etype> void sortedList<Etype>:: insert(const Etype &x){ for (node *p = head; p->next != NULL; p = p->next) { if (p->next->element > x) { current = p; break; } } list<Etype>::insert(x);}

Page 14: Chapter 3: Lists, Stacks, and Queues

CS 340 Page 14

#include "SortedList.h"#include <iostream>using namespace std;void printList(list<int> &lst);// The main function generates a couple of integer lists// to test the functionality of the linked list class.void main(){ sortedList<int> lst1, lst2; cout << "(This should be empty)" << endl; printList(lst1); for (int i = 1; i <= 5; i++) lst1.insertAsFirstElement(i); cout << "(This should be 1 2 3 4 5)" << endl; printList(lst1); for (int i = 4; i <= 6; i++) if (lst1.find(i)) cout << "Found " << lst1() << endl; else cout << i << " not found" << endl; lst2 = lst1; cout << "(This should be 1 2 3 4 5)" << endl; printList(lst2); lst2.remove(3); cout << "(This should be 1 2 4 5)" << endl; printList(lst2); cout << "(but this should still be 1 2 3 4 5)" << endl; printList(lst1);}

A Test Driver For The Sorted List Implementation

// The printList function outputs the contents// of the linked list, starting at the head.void printList(list<int> &lst){ if (lst.isEmpty()) cout << "Empty list." << endl; else for (lst.first(); !lst; ++lst) cout << lst() << endl;}

Page 15: Chapter 3: Lists, Stacks, and Queues

CS 340 Page 15

Example List Application: PolynomialsLet Etype be a two-field structure containing the

coefficient and exponent of each monomial within the polynomial.

Sort the nodes comprising each polynomial based upon the values of their exponents.Polynomial p1(x) = 35x6 - 7x4 + 19x - 5

35 6 -7 4 19 1 -5 0

Polynomial p2(x) = -3x8 + 20x3 - 4x

-3 8 20 3 -4 1

The operations for this ADT could include:

Addition, subtraction, and multiplication of polynomials

Derivatives of polynomials Evaluation of polynomials (i.e.,

plugging in values)

Page 16: Chapter 3: Lists, Stacks, and Queues

CS 340 Page 16

STL List Alternative #1: vectorThe C++ Standard Template Library provides a built-in implementation of a list ADT: the vector.

#include <vector>#include <iostream>using namespace std;

void printVector(vector<int> &vec);// The main function generates two integer lists// to test the functionality of the vector class.void main(){ vector<int> vec1, vec2; cout << "(This should be empty)" << endl; printVector(vec1); vector<int>::iterator itr = vec1.begin(); for (int i = 1; i <= 5; i++) itr = vec1.insert(itr, i); cout << "(This should be 5 4 3 2 1)" << endl; printVector(vec1); for (int val = 4; val <= 6; val++) { int i = 0; bool found = false; while ( (i < vec1.size()) && (!found) ) if (vec1.at(i) == val) { found = true; cout << "Found " << val << endl; } else i++; if (!found) cout << val << " not found" << endl; } vec2 = vec1; cout << "(This should be 5 4 3 2 1)" << endl; printVector(vec2); for (vector<int>::iterator itr = vec2.begin(); itr != vec2.end(); itr++) if (*itr == 3) itr = vec2.erase(itr);

cout << "(This should be 5 4 2 1)" << endl; printVector(vec2); cout << "(but this should still be 5 4 3 2 1)" << endl; printVector(vec1);}

// The printVector function outputs the entire// contents of the vector.void printVector(vector<int> &vec){ if (vec.empty()) cout << "Empty vector." << endl; else for (vector<int>::iterator itr = vec.begin(); itr != vec.end(); itr++) cout << *itr << endl;}

The Good News

Like arrays, vectors are indexable in

constant time.

The Bad NewsInsertion and

removal is expensive,

except at the end of the

vector.

Page 17: Chapter 3: Lists, Stacks, and Queues

CS 340 Page 17

STL List Alternative #2: listThe C++ STL also provides a second built-in implementation of a list ADT: the list.

#include <list>#include <iostream>using namespace std;

void printList(list<int> &lst);

// The main function generates two integer lists// to test the functionality of the list class.void main(){ list<int> lst1, lst2; cout << "(This should be empty)" << endl; printList(lst1); for (int i = 1; i <= 5; i++) lst1.push_front(i); cout << "(This should be 5 4 3 2 1)" << endl; printList(lst1); for (int val = 4; val <= 6; val++) { list<int>::iterator itr = lst1.begin(); bool found = false; while ( (itr != lst1.end()) && (!found) ) if (*itr == val) { found = true; cout << "Found " << val << endl; } else itr++; if (!found) cout << val << " not found" << endl; } lst2 = lst1; cout << "(This should be 5 4 3 2 1)" << endl; printList(lst2); for (list<int>::iterator itr = lst2.begin(); itr != lst2.end(); itr++) if (*itr == 3) itr = lst2.erase(itr);

cout << "(This should be 5 4 2 1)" << endl; printList(lst2); cout << "(but this should still be 5 4 3 2 1)" << endl; printList(lst1);}

// The printList function outputs the entire// contents of the vector.void printList(list<int> &lst){ if (lst.empty()) cout << "Empty list." << endl; else for (list<int>::iterator itr = lst.begin(); itr != lst.end(); itr++) cout << *itr << endl;}

The Good News

Insertion and

removal at any known position is

inexpensive.

The Bad NewsLike traditional linked lists, this doubly linked

list is not easily indexable.

Page 18: Chapter 3: Lists, Stacks, and Queues

CS 340 Page 18

ADT #2: The StackA stack is a list in which insertions and removals can only transpire at one end of the list, i.e., the top of the stack.

stk.pop( )

stk.push()

Page 19: Chapter 3: Lists, Stacks, and Queues

CS 340 Page 19

Example Stack Application: Arithmetic ExpressionsStacks can be used to convert infix expressions into

postfix expressions

Following these rules, then, the infix expression 7 + 6 - 3 * ( 5 + 8 / 2 ) is converted into the postfix expression 7 6 + 3 5 8 2 / + * -

When this is encountered in an infix expression...

… then do this!

the beginning of the infix expression push a # onto the stack

an operand append it to the postfix expression

a right parenthesis repeatedly pop the stack, appending each entry to the postfix expression, until a left parenthesis is popped (but not output)

the end of the infix expression repeatedly pop the stack, adding each entry to the expression

a left parenthesis push it onto the stack

a * or / operatorrepeatedly pop the stack, appending all popped * and /

operators to the end of the postfix expression, until something else is popped; push this last item back onto the

stack, followed by the new * or / that was encountered

a + or - operatorrepeatedly pop the stack, appending all popped +, -, *, and /

operators to the end of the postfix expression, until something else is popped; push this last item back onto the

stack, followed by the new + or - that was encountered

Page 20: Chapter 3: Lists, Stacks, and Queues

CS 340 Page 20

Arithmetic Expression Evaluation (continued)Then a separate stack can be used to evaluate the

postfix expression

Following these rules with the postfix expression 7 6 + 3 5 8 2 / + * - yields:

7 76

13 133

1335

13358

133582

13354

1339

1327

-14

When this is encountered in a postfix

expression...… then do this!

an operand push it onto the stack

An operatorpop the stack twice, perform the operation on the two popped operands, and push the result

back onto the stackthe end of the postfix

expressionpop the stack once; the popped value is the

final result

Page 21: Chapter 3: Lists, Stacks, and Queues

CS 340 Page 21

Example Stack Application: The Run-Time Stack Stores local data and call

information for nested procedures in a program

Grows downward from its origin

Stack pointer points to current topmost data item on the stack

Push operation decrements pointer and copies data to stack

Pop operation copies data from stack and then increments pointer

Each procedure called in the program stores procedure return information (in yellow) and local data (in other colors) by pushing them onto stack

Page 22: Chapter 3: Lists, Stacks, and Queues

CS 340 Page 22

Stack Implementation Alternatives An Array Implementation

– Positives• Trivial implementation due to

indexing– Negatives

• Size must be declared in advance A Linked List Implementation

– Positives• Dynamically allocates the right

amount of memory• Straightforward (if not quite trivial)

implementation– Negatives

• Wastes memory for pointers that are underutilized

Page 23: Chapter 3: Lists, Stacks, and Queues

CS 340 Page 23

ADT #3: The Queue

que.dequeue( )

que.enqueue()

A queue is a list in which insertions can only occur at one end of the list (the front of the queue) and removals can only occur at the opposite end of the list (the back of the queue).

Page 24: Chapter 3: Lists, Stacks, and Queues

CS 340 Page 24

Example Queue Application: Server AccessThe “first-come, first-served” nature of the queue ADT can be adapted to providing orderly access to file servers, print servers, Web servers, etc.

Moe’sPrintJob #1

Larry’s

PrintJob #1

Moe’sPrintJob #2

Curly’s

PrintJob #1

Page 25: Chapter 3: Lists, Stacks, and Queues

CS 340 Page 25

Example Queue Application: Breadth-First Search

bfs(v) enqueue(v) while queue not empty v=dequeue() process(v) for all unvisited vertices i adjacent to v mark i as visited enqueue(i)

Search a tree structure for a goal, beginning at the root node and exploring all neighboring nodes

Use a queue to remember which nodes have yet to be fully explored

If the queue is ever empty without the goal being found, then the goal isn’t in the tree

Page 26: Chapter 3: Lists, Stacks, and Queues

CS 340 Page 26

Queue Implementation Alternatives An Array Implementation

– Positives• Straightforward implementation

due to indexing– Negatives

• Size must be declared in advance• Wraparound is needed to avoid

false overflows A Linked List Implementation

– Positives• Dynamically allocates the right

amount of memory• Wraparound problem is

circumvented– Negatives

• Wastes memory for pointers that are underutilized