programming abstraction in c++qiao/courses/cs2so3/slides/linear.pdfprogramming abstraction in c++...
TRANSCRIPT
Introduction Stacks Queues Vectors
Programming Abstraction in C++
Eric S. Roberts and Julie Zelenski
Stanford University2010
Introduction Stacks Queues Vectors
Chapter 11. Linear Structures
Introduction Stacks Queues Vectors
Outline
1 Introduction
2 StacksArray implementationLinked list implementation
3 QueuesArray implementationLinked list implementation
4 Vectors
Introduction Stacks Queues Vectors
Outline
1 Introduction
2 StacksArray implementationLinked list implementation
3 QueuesArray implementationLinked list implementation
4 Vectors
Introduction Stacks Queues Vectors
Introduction
Linear structures
Stack
Queue
Vector
Goals
Different (array and linked list) implementations of theselinear structures.
Introduce template in C++ and polymorphic classes.
Introduction Stacks Queues Vectors
Outline
1 Introduction
2 StacksArray implementationLinked list implementation
3 QueuesArray implementationLinked list implementation
4 Vectors
Introduction Stacks Queues Vectors
Template
Changing CharStack to a general Stack template so the stackelement can be of any type.
Add the following line before a syntactic unit, such as classdefinition, 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 asFigure 9-1, p. 320-321, except that the element type char isreplaced 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 StacksArray implementationLinked list implementation
3 QueuesArray implementationLinked 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 firstand the end elements.
Introduction Stacks Queues Vectors
Array implementation
Two indexes: head and tail, for easy access to the firstand the end elements.
To use space efficiently, we “wrap around” the queue fromthe end of the array back to position 0.
tail
F G H I JK
5 1
0 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 firstand the end elements.
To use space efficiently, we “wrap around” the queue fromthe end of the array back to position 0.
tail
F G H I JK
5 1
0 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 fullqueue, we limit the number of elements in the queue to oneless than the number of elements in the array. Thus thecondition 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 fullqueue, we limit the number of elements in the queue to oneless than the number of elements in the array. Thus thecondition 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 aspecial 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 aspecial 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 StacksArray implementationLinked list implementation
3 QueuesArray implementationLinked list implementation
4 Vectors
Introduction Stacks Queues Vectors
Introduction
Dynamic array implementation. Similar to the dynamic arrayrepresentation of the editor buffer, for example, insertion anddeletion.
Introduction Stacks Queues Vectors
Introduction
Dynamic array implementation. Similar to the dynamic arrayrepresentation of the editor buffer, for example, insertion anddeletion.
New issues:
Check bounds.
Square bracket selection.
Iterator.
Introduction Stacks Queues Vectors
Introduction
Dynamic array implementation. Similar to the dynamic arrayrepresentation of the editor buffer, for example, insertion anddeletion.
New issues:
Check bounds.
Square bracket selection.
Iterator.
Interface, vector.h, Figure 11-11, pp. 405-408. It includesthe usual operations and square bracket operator and nestedclass 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 keywordoperator.
Return by reference using an &, so values can be assignedto 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 toVector)
Designate Vector as a friend class, thus Vector classcan see the private variables, such as vp and index, andthe 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 cansee private instance variables such as count.
Vector public method prototype iterator.
Introduction Stacks Queues Vectors
Implementing iterators (cont.)
Idiom: Declaring an iteratorVector<int>::Iterator iter = vec.iterator();
Introduction Stacks Queues Vectors
Implementing iterators (cont.)
Idiom: Declaring an iteratorVector<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 theparameter 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 parameterand index to 0.Note. Iterator now can see Vector private variablesthrough 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 theorder of elements returned by an iterator. For example, theVector method insertAt or removeAt can change thecontent of a vector, whereas Iterator has its own variableindex. In general, iterators make sense only if the structure isstatic.
Introduction Stacks Queues Vectors
A note on the typename keyword
The Vector method iterator on p. 411, the keywordtypename is required for a type/class that is defined inside aclass template when the reference is made outside of theimplementation of that class template.
Why is it outside? Because C++ considers the return type to beoutside the scope of the implementation. You are thereforerequired to qualify the name of the type by using the full nameVector<ElemType>::Iterator rather than just Iterator.You must also precede the return type with the keywordtypename because this type/class is defined within a template.
See p. 437, for the typename keyword.