Homework 4 questions???
Storing a collection of like elements Most programs deal with a collection of like elements Phone contacts Students in a class Circle of friends Elements in a collection can be stored In contiguous memory locations (array, vector) Allows O(1) access to the element at any position Adding and removing elements requires shifting other elements In nodes that are linked together (linked list) Access by position no longer O(1) Adding and removing elements does not require shifting other elements
Container classes Container classes store a collection of like elements only thing a container knows about its elements is their type Provide methods to Add an element Remove an element Retrieve an element Differ in How elements are related to each other How elements are added, removed, retrieved
Some useful container classes Stack Queue List Tree Priority queue Set map
One way in which elements can be accessed By position (position oriented) Each element has a position in the collection First, second, third, ….. , last Typical operations Add an element after the last position Retrieve the element at position 4 Delete the element at the first position Replace the element at position 6 with another element
another way in which elements can be accessed By value (value oriented) Elements are comparable Elements may or may not be kept in order of their values This decision is up to the implementation Typical operations Add an element with a given value Retrieve the element with a given value Is there an element with a given value remove the element with a given value
Ways in which elements can be related to each other Linear (1 - to - 1) Each element has a predecessor and a successor First element has no predecessor, last element has no successor Hierarchical (1 – to – many) Each element has one predecessor and 0 to multiple successors One element (the root) has no predecessor Graph (many to many) Each element has 0 to many predecessors and 0 to many successors Membership Elements do not have predecessors or successors
Is the list ADT defined in zybooks value oriented or position oriented? Operation Description Example starting with list: 99, 77 Append(list, x) Inserts x at end of list Append(list, 44), list: 99, 77, 44 Prepend(list, x) Inserts x at start of list Prepend(list, 44), list: 44, 99, 77 InsertAfter(list, w, x) Inserts x after w InsertAfter(list, 99, 44), list: 99, 44, 77 Remove(list, x) Removes x Remove(list, 77), list: 99 Search(list, x) Returns item if found, else returns 0 Search(list, 99), returns item 99 Search(list, 22), returns 0 Print(list) Prints list's items in order Print(list) outputs: 99, 77 PrintReverse(list) Prints list's items in reverse order PrintReverse(list) outputs: 77, 99 Sort(list) Sorts the lists items in ascending order list becomes: 77, 99 IsEmpty(list) Returns true if list has no items For list 99, 77, IsEmpty(list) returns false GetLength(list) Returns the number of items in the list GetLength(list) returns 2
Two linear position oriented adts Operation Description Push(stack, x) Inserts x on top of stack Pop(stack) Returns and removes item at top of stack Peek(stack) Returns but does not remove item at top of stack IsEmpty(stack) Returns true if stack has no items GetLength(stack) Returns the number of items in the stack Stack Operation Description Push(queue, x) Inserts x at end of the queue Pop(queue) Returns and removes item at front of queue Peek(queue) Returns but does not remove item at the front of the queue IsEmpty(queue) Returns true if queue has no items GetLength(queue) Returns the number of items in the queue Queue
Quiz 4 After performing the following operations on an initially empty stack of characters: push (a) push (x) Push (D) pop () what will be returned by peek()? After performing the following operations on an initially empty queue of characters: push (a) push (x) Push (D) pop () what will be returned by peek()? A queue has first-in last-out behavior (true or false)
Quiz 4 After performing the following operations on an initially empty stack of characters: push (a) push (x) Push (D) pop () what will be returned by peek()? x After performing the following operations on an initially empty queue of characters: push (a) push (x) Push (D) pop () what will be returned by peek()? x A queue has first-in last-out behavior (true or false)
The stack adt All operations occur at one end of the sequence (the top) Has LIFO (last in, first out) behavior
The queue adt operations occur at both ends of the sequence (add at front, remove from rear) Has FIFO (first in, first out) behavior
Specification of the adt stack describes operations and their behavior, not element type or how the elements will be stored (data structure) Operation Description Push(stack, x) Inserts x on top of stack Pop(stack) Returns and removes item at top of stack Peek(stack) Returns but does not remove item at top of stack IsEmpty(stack) Returns true if stack has no items GetLength(stack) Returns the number of items in the stack
C++ specification of the adt stack Leaves the decision about the type of elements to be stored to the user of the class by defining a template class allows the class user to create a stack<mytype> just like creating a vector<mytype> Leaves the decision about the data structure to use to hold the elements to the implementation by defining an abstract base class like a java interface Specifies methods that must be implemented by a subclass
// file: StackInterface.h #ifndef STACK_INTERFACE_ #define STACK_INTERFACE_ template<class ItemType> class StackInterface { public: virtual bool isEmpty() const = 0; // input: none // output: return true if the stack is empty; else false virtual bool push(const ItemType& newEntry) = 0; // input: item to be added to stack // output: returns true if item is added; else false virtual bool pop() = 0; // output: returns true if top of stack has been removed; // else false virtual ItemType peek() const = 0; // precondition: stack is not empty // output: returns a copy of the top item on the stack virtual ~StackInterface() { } // destructor }; #endif
What does implementation of a container class require? Choose how to store the collection of elements Possible choices Array, vector, linked list Implement methods in the adt’s specification
// file ArrayStack.h #ifndef ARRAY_STACK_ #define ARRAY_STACK_ #include "StackInterface.h" template<class ItemType> class ArrayStack : public StackInterface<ItemType> { private: static const int DEFAULT_CAPACITY = 50; ItemType items[DEFAULT_CAPACITY]; // static array int top; public: ArrayStack(); // Default constructor bool isEmpty() const; bool push(const ItemType& newEntry); bool pop(); ItemType peek() const; }; #include "ArrayStack.cpp" #endif;
template<class ItemType> bool ArrayStack<ItemType>::isEmpty() const { return top < 0; } bool ArrayStack<ItemType>::pop(){ bool result = false; if (!isEmpty()){ top--; result = true; return result; ItemType ArrayStack<ItemType>::peek() const{ assert(!isEmpty()); // enforce precondition return items[top]; // file: ArrayStack.cpp #include <cassert> // for assert function #include "ArrayStack.h" template<class ItemType> ArrayStack<ItemType>::ArrayStack() : top(-1) { } bool ArrayStack<ItemType>::push(const ItemType& newEntry) { bool result = false; if (top < DEFAULT_CAPACITY – 1 { top++; items[top] = newEntry; result = true; return result;
What does program using this stack need to do? #include arraystack.h Arraystack<int> intstack; Arraystack<mytype> stack; Call stack methods as needed to do the job
Process for defining and implementing a container class – using stack as an example Specify the operations and their behavior Independent of any programming language define a c++ abstract base class -- stackinterface Provide Operations as pure virtual methods Provide No implementation Define and implement a subclass of stackinterface -- arraystack Pick a data structure for holding the stack elements Implement the pure virtual methods inherited from stackinterface Provide a constructor and any other methods needed
Next steps In lab on Friday will define and implement a subclass of stackinterface that Implements a stack using a vector as the implementation data structure In Homework 5 will Implement a stack using a linked list as the implementation data structure Use a stack to evaluate postfix expressions
A linked list head element element element a node a node a node Elements are stored in nodes that are in non-contiguous memory locations Nodes are linked together using pointers Class implementer has to allocate and free space for nodes
pointers Variables of type pointer have a value which is a memory address Example: string* spointer ; spointer is of type pointer to a string String s = “CS240C”; Spointer = &s;
Do not mistake the pointing finger for the moon SPOINTER S CS240C cout >> SPOINTER >> endl; cout >> S >> endl; cout >> *SPOINTER >> endl;
the new and delete operators New allocates (at run time) memory space to store a value of some type and returns the address of that block of memory String* sptr = new string(“c++”); Myclass* ptr = new myclass(-----); Delete frees up the block of memory a pointer points to Delete sptr; Sptr = nullptr; Delete ptr; Ptr = nullptr; Every new needs a delete
Elements of a linked list are stored in nodes When an element is added to a linked list, a node is allocated using new The element is stored in the node The node has to be linked into the linked list When an element is removed from a linked list, the node it occupied is freed using delete Nodes of the linked list need to relinked by changes to some pointers
A node Where should the Node class be defined? template<class ItemType> class Node { public: ItemType data; Node * next; }; data next Where should the Node class be defined?
head->data or (*head).data head->next head->next->data 56 93 78 What is the value of: head *head head->data or (*head).data head->next head->next->data head->next->next->next
head the address of the node containing 56 93 78 What is the value of: head the address of the node containing 56 *head the node containing 56 head->data or (*head).data 56 head->next the address of the node containing 93 head->next->data 93 head->next->next->next nullptr
Some questions Which end of a linked list should the push and pop operations affect? What data members are needed by a linked list implementation of a stack? What does an empty linked list look like?
Some questions Which end of a linked list should the push and pop operations affect? The front of the linked list What data members are needed by a linked list implementation of a stack? Node* head/top/--- Int size What does an empty linked list look like?
Given the linked list shown write code to add the value 36 at the beginning top 56 93 78 Allocate a node Store 36 in it Link this node into the existing linked list (at the beginning)
Node* p = new Node; p->data = 36; p->next = top; top = p; top 56 93 78 Node* p = new Node; p->data = 36; p->next = top; top = p;
Given the linked list shown write code to display the data in the list top 56 93 78 Use a temporary node pointer to traverse the list
Given the linked list shown write code to display the data in the list top 56 93 78 Node* temp = top; while (temp != nullptr) { cout >> temp->data >> endl; temp = temp->next; }
Expression evaluation Arithmetic expressions are written using infix notation each operator appears between its operands order in which operators are used depends on precedence rules (* and / have higher precedence than + and -) parenthesis in what order are the operators used: 3 + 2 * 5 (3 + 2) * 5 most compilers convert an infix expression to postfix and then evaluate the postfix expression each operator appears after its operands postfix expressions have no parentheses 3 2 5 * + 3 2 + 5 *
Evaluating a postfix expression Expressions are made up of a sequence of tokens Tokens are either operators or operands Evaluation is done one token at a time Operands have to wait for their operator Push them on to a stack When an operator is reached its operands are waiting on the stack Get the operands from the stack Apply the operator Push the result (an operand) onto the stack After all tokens are processed the result should be the only element on the stack
algorithm to evaluate a postfix expression create an empty stack while there are more tokens in the postfix expression get the next token if the token is an operand push it onto the stack if the token is an operator get and pop the top two operands from the stack apply the operator to these two operands push the result onto the stack the top of the stack is the result of evaluating the postfix expression