Introduction Stacks Queues Vectors
Programming Abstraction in C++ Eric S. Roberts and Julie Zelenski - - PowerPoint PPT Presentation
Programming Abstraction in C++ Eric S. Roberts and Julie Zelenski - - PowerPoint PPT Presentation
Introduction Stacks Queues Vectors Programming Abstraction in C++ Eric S. Roberts and Julie Zelenski Stanford University 2010 Introduction Stacks Queues Vectors Chapter 11. Linear Structures Introduction Stacks Queues Vectors
Introduction Stacks Queues Vectors
Chapter 11. Linear Structures
Introduction Stacks Queues Vectors
Outline
1
Introduction
2
Stacks Array implementation Linked list implementation
3
Queues Array implementation Linked list implementation
4
Vectors
Introduction Stacks Queues Vectors
Outline
1
Introduction
2
Stacks Array implementation Linked list implementation
3
Queues Array implementation Linked list implementation
4
Vectors
Introduction Stacks Queues Vectors
Introduction
Linear structures Stack Queue Vector Goals Different (array and linked list) implementations of these linear structures. Introduce template in C++ and polymorphic classes.
Introduction Stacks Queues Vectors
Outline
1
Introduction
2
Stacks Array implementation Linked list implementation
3
Queues Array implementation Linked list implementation
4
Vectors
Introduction Stacks Queues Vectors
Template
Changing CharStack to a general Stack template so the stack element can be of any type. Add the following line before a syntactic unit, such as class definition, and before each of the method implementations. template <typename ElemType>
Introduction Stacks Queues Vectors
Example
Before class definition: template <typename ElemType> class Stack { public: . . . private: #include "stackpriv.h" };
Introduction Stacks Queues Vectors
Example
Before each of the method implementations: template <typename ElemType> Stack<ElemType>::Stack { capacity = INITIAL_CAPACITY; elements = new ElemType[capacity]; count = 0; } Such classes are said to be polymorphic.
Introduction Stacks Queues Vectors
Interface
The interface Figure 11-1, pp. 384-385, remains the same as Figure 9-1, p. 320-321, except that the element type char is replaced by ElemType. Include different private data and implementation files to “hide” implementation detail. private: #include "stackpriv.h" #include "stackimpl.cpp"
Introduction Stacks Queues Vectors
Array implementation
Array implementation (partial): Figure 11-2, Figure 11-3, pp. 386-387. Almost identical to CharStack with dynamic array: Figure 9-2, pp. 323-324, implementation on p. 326.
Introduction Stacks Queues Vectors
Linked list implementation
No cursor, no dummy cell. The empty stack is represented by the NULL pointer. count for the stack size. The implementation of the methods is straightforward. Figures 11-4 and 11-5, pp. 388-390.
Introduction Stacks Queues Vectors
struct cellT { ElemType data; cellT *link; }; cellT *list; int count;
Introduction Stacks Queues Vectors
stackimpl.cpp
template <typename ElemType> void Stack<ElemType>::push(ElemType elem) { cellT *cell = new cellT; cell->data = elem; cell->link = list; list = cell; count++; }
Introduction Stacks Queues Vectors
stackimpl.cpp
template <typename ElemType> ElemType Stack<ElemType>::pop() { if (isEmpty()) { Error("pop: Empty stack"); } cellT *cell = list; ElemType result = cell->data; list = list->link; count--; delete cell; return result; }
Introduction Stacks Queues Vectors
Outline
1
Introduction
2
Stacks Array implementation Linked list implementation
3
Queues Array implementation Linked list implementation
4
Vectors
Introduction Stacks Queues Vectors
Interface
Interface, Figure 11-6, p. 392. Similar to stack, except two operations enqueue adds an element to the end of the queue dequeue removes the first element from the queue
Introduction Stacks Queues Vectors
Array implementation
Two indexes: head and tail, for easy access to the first and the end elements.
Introduction Stacks Queues Vectors
Array implementation
Two indexes: head and tail, for easy access to the first and the end elements. To use space efficiently, we “wrap around” the queue from the end of the array back to position 0.
tail
F G H I J K 5 1
1 2 3 4 5 6 7 8 9 head
Introduction Stacks Queues Vectors
Array implementation
Two indexes: head and tail, for easy access to the first and the end elements. To use space efficiently, we “wrap around” the queue from the end of the array back to position 0.
tail
F G H I J K 5 1
1 2 3 4 5 6 7 8 9 head
This representation is called ring buffer.
Introduction Stacks Queues Vectors
Array implementation (cont.)
Technique: modular arithmetic %
- Example. The size of the queue is
(tail + capacity - head) % capacity
Introduction Stacks Queues Vectors
Array implementation (cont.)
Technique: modular arithmetic %
- Example. The size of the queue is
(tail + capacity - head) % capacity When tail≥head, the size is tail−head= (tail + capacity - head) % capacity. When tail<head, unwrap the queue and the size is tail+capacity−head.
Introduction Stacks Queues Vectors
Array implementation (cont.)
To avoid the confusion between an empty queue and a full queue, we limit the number of elements in the queue to one less than the number of elements in the array. Thus the condition for a full queue is size() == capacity - 1 See the method enqueue, p. 307.
Introduction Stacks Queues Vectors
Array implementation (cont.)
To avoid the confusion between an empty queue and a full queue, we limit the number of elements in the queue to one less than the number of elements in the array. Thus the condition for a full queue is size() == capacity - 1 See the method enqueue, p. 307. Private data, p. 319. Implementation, Figure 11-7, pp. 396-398.
Introduction Stacks Queues Vectors
Linked list implementation
Two pointers: head and tail. An empty queue is represented by NULL in head. The enqueue must check for the empty queue as a special case.
Introduction Stacks Queues Vectors
Linked list implementation
Two pointers: head and tail. An empty queue is represented by NULL in head. The enqueue must check for the empty queue as a special case. Similar to the linked list representation of the editor buffer.
Introduction Stacks Queues Vectors
enqueue
template <typename ElemType> void Queue<ElemType>::enqueue(ElemType elem) { cellT *cellPtr = new cellT; cellPtr->data = elem; cellPtr->link = NULL; if (isEmpty()) { head = cellPtr; } else { tail->link = cellPtr; } tail = cellPtr; count++; }
Introduction Stacks Queues Vectors
dequeue
template <typename ElemType> void Queue<ElemType>::isEmpty() { return (head == NULL); } template <typename ElemType> ElemType Queue<ElemType>::dequeue() { if (isEmpty()) Error("..."); cellT *cellPtr = head; ElemType result = cellPtr->data; head = cellPtr->link; count--; delete cellPtr; return result; }
Introduction Stacks Queues Vectors
Outline
1
Introduction
2
Stacks Array implementation Linked list implementation
3
Queues Array implementation Linked list implementation
4
Vectors
Introduction Stacks Queues Vectors
Introduction
Dynamic array implementation. Similar to the dynamic array representation of the editor buffer, for example, insertion and deletion.
Introduction Stacks Queues Vectors
Introduction
Dynamic array implementation. Similar to the dynamic array representation of the editor buffer, for example, insertion and deletion. New issues: Check bounds. Square bracket selection. Iterator.
Introduction Stacks Queues Vectors
Introduction
Dynamic array implementation. Similar to the dynamic array representation of the editor buffer, for example, insertion and deletion. New issues: Check bounds. Square bracket selection. Iterator. Interface, vector.h, Figure 11-11, pp. 405-408. It includes the usual operations and square bracket operator and nested class Iterator.
Introduction Stacks Queues Vectors
vecpriv.h
Figure 11-12, p. 408 static const int INITIAL_CAPACITY = 100; ElementType *elements; int capacity; int count; void expandCapacity(); Similar to the array editor buffer, p. 347.
Introduction Stacks Queues Vectors
Check bounds
template <typename ElemType> void Vector<ElemType>::insertAt(int index, ElemType elem) { if (count == capacity) expandCapacity(); if (index < 0 || index > count) { Error("insertAt: index out of range"); } for (int i = count; i > index; i--) { elements[i] = elements[i-1]; } elements[index] = elem; count++; }
Introduction Stacks Queues Vectors
Implementing selection brackets
Redefine operators for a particular class using the keyword
- perator.
Return by reference using an &, so values can be assigned to an element selected using square brackets, for example, vec[i] = vec[i - 1].
template <typename ElemType> ElemType & Vector<ElemType>::operator[] (int index) { if (index < 0 || index >= count) { Error("Vector selection index out of range"); } return elements[index]; }
Introduction Stacks Queues Vectors
Implementing iterators
A nested class, a class within a class. In vector.h: Defining the Iterator class within the Vector class
class Iterator { public: Iterator(); bool hasNext(); ElemType next(); private: Vector *vp; int index; Iterator(Vector *vp); friend class Vector; }; friend class Iterator;
Introduction Stacks Queues Vectors
Implementing iterators (cont.)
The public section
public: Iterator(); bool hasNext(); ElemType next();
A public (Iterator) constructor, no parameters Two public (Iterator) method prototypes
Introduction Stacks Queues Vectors
Implementing iterators (cont.)
In the private section
private: Vector *vp; int index; Iterator(Vector *vp); friend class Vector;
Two instance variables, as expected A private constructor (with a parameter, a pointer to Vector) Designate Vector as a friend class, thus Vector class can see the private variables, such as vp and index, and the private constructor Iterator.
Introduction Stacks Queues Vectors
Implementing iterators (cont.)
Outside the Iterator class, within the Vector class,
friend class Iterator; Iterator iterator();
Designate Iterator as friend class, thus Iterator can see private instance variables such as count. Vector public method prototype iterator.
Introduction Stacks Queues Vectors
Implementing iterators (cont.)
Idiom: Declaring an iterator
Vector<int>::Iterator iter = vec.iterator();
Introduction Stacks Queues Vectors
Implementing iterators (cont.)
Idiom: Declaring an iterator
Vector<int>::Iterator iter = vec.iterator();
Implementation of Vector method iterator:
template <typename ElemType> typename Vector<ElemType>::Iterator Vector<ElemType>::iterator() { return Iterator(this); }
It calls Iterator private constructor passing this as the parameter and returns an object of Iterator class.
- Note. Vector can see Iterator private constructor.
Introduction Stacks Queues Vectors
Implementing iterators (cont.)
Implementation of Iterator private constructor
template <typename ElemType> Vector<ElemType>::Iterator::Iterator(Vector *vp) { this->vp = vp; index = 0; }
It sets the Iterator instance variable vp to the parameter and index to 0.
- Note. Iterator now can see Vector private variables
through its own private variable vp.
Introduction Stacks Queues Vectors
Implementing vectors
Figure 11-12, p. 408, private data file. Figure 11-13, pp. 409-412, implementation file.
Introduction Stacks Queues Vectors
Implementing vectors
Figure 11-12, p. 408, private data file. Figure 11-13, pp. 409-412, implementation file.
- Important. Changes to the content of a vector can invalidate the
- rder of elements returned by an iterator. For example, the
Vector method insertAt or removeAt can change the content of a vector, whereas Iterator has its own variable
- index. In general, iterators make sense only if the structure is
static.
Introduction Stacks Queues Vectors
A note on the typename keyword
The Vector method iterator on p. 411, the keyword typename is required for a type/class that is defined inside a class template when the reference is made outside of the implementation of that class template. Why is it outside? Because C++ considers the return type to be
- utside the scope of the implementation. You are therefore