Programming Abstraction in C++ Eric S. Roberts and Julie Zelenski - - PowerPoint PPT Presentation

programming abstraction in c
SMART_READER_LITE
LIVE PREVIEW

Programming Abstraction in C++ Eric S. Roberts and Julie Zelenski - - PowerPoint PPT Presentation

An Editor Buffer Implementation I: Character Array Implementation II: Stacks Implementation III: Linked List Programming Abstraction in C++ Eric S. Roberts and Julie Zelenski Stanford University 2010 An Editor Buffer Implementation I:


slide-1
SLIDE 1

An Editor Buffer Implementation I: Character Array Implementation II: Stacks Implementation III: Linked List

Programming Abstraction in C++

Eric S. Roberts and Julie Zelenski

Stanford University 2010

slide-2
SLIDE 2

An Editor Buffer Implementation I: Character Array Implementation II: Stacks Implementation III: Linked List

Chapter 10. Efficiency and Data Representation

slide-3
SLIDE 3

An Editor Buffer Implementation I: Character Array Implementation II: Stacks Implementation III: Linked List

Outline

1

An Editor Buffer

2

Implementation I: Character Array

3

Implementation II: Stacks

4

Implementation III: Linked List

slide-4
SLIDE 4

An Editor Buffer Implementation I: Character Array Implementation II: Stacks Implementation III: Linked List

Outline

1

An Editor Buffer

2

Implementation I: Character Array

3

Implementation II: Stacks

4

Implementation III: Linked List

slide-5
SLIDE 5

An Editor Buffer Implementation I: Character Array Implementation II: Stacks Implementation III: Linked List

Introduction

Goal Use editor buffer as an example to illustrate how the choice of data representation affects the efficiency of applications. Method Use a low-level built-in structure, such as character array, so the operations are visible and thus easier to assess efficiency. Lesson Find options and evaluate the trade-offs. A good design demands compromise. Important The external behavior of an editor buffer (Table 10-1, p. 340) must remain the same while implementation changes.

slide-6
SLIDE 6

An Editor Buffer Implementation I: Character Array Implementation II: Stacks Implementation III: Linked List

Operations

Move the cursor forward one position moveCursorForward() Move the cursor backward one position moveCursorBackward() Jump the cursor to the beginning (before the first character) moveCursorToStart() Move the cursor to the end (after the last character) moveCursorToEnd() Insert a character at the current cursor position insertCharacter(char ch) Delete the character just after the cursor position deleteCharacter() Desplay the content of the buffer display()

slide-7
SLIDE 7

An Editor Buffer Implementation I: Character Array Implementation II: Stacks Implementation III: Linked List

Interface design

Constructor EditorBuffer() Destructor ˜EditorBuffer()

slide-8
SLIDE 8

An Editor Buffer Implementation I: Character Array Implementation II: Stacks Implementation III: Linked List

Interface design

Constructor EditorBuffer() Destructor ˜EditorBuffer() Commands: F: move forward B: move backward J: jump to beginning E: jump to end Ixxx: insert characters xxx D: delete Q: quit editor

slide-9
SLIDE 9

An Editor Buffer Implementation I: Character Array Implementation II: Stacks Implementation III: Linked List

Interface design (cont.)

The interface, the public section, Figure 10-1, p. 343-344. Study Documentation Style (boilerplate, class definition) The public method prototypes The private section is included from a file bufpriv.h

slide-10
SLIDE 10

An Editor Buffer Implementation I: Character Array Implementation II: Stacks Implementation III: Linked List

Interface design (cont.)

The interface, the public section, Figure 10-1, p. 343-344. Study Documentation Style (boilerplate, class definition) The public method prototypes The private section is included from a file bufpriv.h Now that you have the interface, you can write an application program solely based on it, without knowing the

  • implementation. The application program should not be

affected when implementation changes.

slide-11
SLIDE 11

An Editor Buffer Implementation I: Character Array Implementation II: Stacks Implementation III: Linked List

Command-driven editor

Figure 10-2, p. 346 Pattern: command-driven editor

int main() { EditorBuffer buffer; while (true) { cout << "*"; string cmd = GetLine(); if (cmd != "") ExecuteCommand(buffer, cmd); buffer.display(); } return 0; }

slide-12
SLIDE 12

An Editor Buffer Implementation I: Character Array Implementation II: Stacks Implementation III: Linked List

Command-driven editor

Figure 10-2, p. 346 Pattern: command-driven editor

int main() { EditorBuffer buffer; while (true) { cout << "*"; string cmd = GetLine(); if (cmd != "") ExecuteCommand(buffer, cmd); buffer.display(); } return 0; }

A shell program is similar.

slide-13
SLIDE 13

An Editor Buffer Implementation I: Character Array Implementation II: Stacks Implementation III: Linked List

Command-driven editor (cont.)

void ExecuteCommand(EditorBuffer & buffer, string line) { switch (toupper(line[0]) { case ’I’: for (int i = 1; i < line.length(); i++) { buffer.insertCharacter(line[i]); } break; case ’D’: buffer.deleteCharacter(); break; case ’F’: buffer.moveCursorForward(); break; case ’B’: buffer.moveCursorBackward(); break; case ’J’: buffer.moveCursorToStart(); break; case ’E’: buffer.moveCursorToEnd(); break; case ’Q’: exit(0); default: cout << "Illegal command" << endl; break; } }

slide-14
SLIDE 14

An Editor Buffer Implementation I: Character Array Implementation II: Stacks Implementation III: Linked List

Outline

1

An Editor Buffer

2

Implementation I: Character Array

3

Implementation II: Stacks

4

Implementation III: Linked List

slide-15
SLIDE 15

An Editor Buffer Implementation I: Character Array Implementation II: Stacks Implementation III: Linked List

Private data representation

Buffer A character array of fixed capacity, which can be extended like the dynamic CharStack. Current length of the buffer. cursor Position, the index of the character that immediately follows the cursor.

slide-16
SLIDE 16

An Editor Buffer Implementation I: Character Array Implementation II: Stacks Implementation III: Linked List

Private data representation

Buffer A character array of fixed capacity, which can be extended like the dynamic CharStack. Current length of the buffer. cursor Position, the index of the character that immediately follows the cursor. Private instance variables: char *array; int capacity; int length; int cursor;

slide-17
SLIDE 17

An Editor Buffer Implementation I: Character Array Implementation II: Stacks Implementation III: Linked List

Implementing the methods

Moving cursor operations are straightforward. Constructor and destructor, Figure 10-3, p. 349

EditorBuffer::EditorBuffer() { capacity = INITIAL_CAPACITY; array = new char[capacity]; length = 0; cursor = 0; } EditorBuffer::˜EditorBuffer() { delete[] array; }

slide-18
SLIDE 18

An Editor Buffer Implementation I: Character Array Implementation II: Stacks Implementation III: Linked List

moveCursorToEnd

void EditorBuffer::moveCursorToEnd() { cursor = length; }

The size of the array must be at least length + 1.

slide-19
SLIDE 19

An Editor Buffer Implementation I: Character Array Implementation II: Stacks Implementation III: Linked List

Insertion

buffer.insertCharacter(’X’); Before

14

H E L L O

length cursor array capacity 15 5 3

1 2 3 4 5 6 7 8 9 10 11 12 13

slide-20
SLIDE 20

An Editor Buffer Implementation I: Character Array Implementation II: Stacks Implementation III: Linked List

Insertion (cont.)

buffer.insertCharacter(’X’); After

X H E L

length cursor array capacity 15

1 2 3 4 5 6 7 8 9 10 11 12 13 14

O L

4 6

slide-21
SLIDE 21

An Editor Buffer Implementation I: Character Array Implementation II: Stacks Implementation III: Linked List

Insertion (cont.)

Figure 10-3, p. 350

void EditorBuffer::insertCharacter(char ch) { if ((length + 1) == capacity) expandCapacity(); for (int i = length; i > cursor; i--) { array[i] = array[i - 1]; } array[cursor] = ch; length++; cursor++; }

expandCapacity (p. 351) is similar to CharStack counterpart (p.326).

slide-22
SLIDE 22

An Editor Buffer Implementation I: Character Array Implementation II: Stacks Implementation III: Linked List

Insertion (cont.)

Figure 10-3, p. 350

void EditorBuffer::insertCharacter(char ch) { if ((length + 1) == capacity) expandCapacity(); for (int i = length; i > cursor; i--) { array[i] = array[i - 1]; } array[cursor] = ch; length++; cursor++; }

expandCapacity (p. 351) is similar to CharStack counterpart (p.326). deleteCharacter (p. 350) is similar.

slide-23
SLIDE 23

An Editor Buffer Implementation I: Character Array Implementation II: Stacks Implementation III: Linked List

Assessing complexity

Problem size N: buffer length Operation count: The operations (comparison, addition, assignment) in moving the cursor are independent of N (constant). No loops.

slide-24
SLIDE 24

An Editor Buffer Implementation I: Character Array Implementation II: Stacks Implementation III: Linked List

Assessing complexity

The operations of copying characters (assignment) in insertion and deletion are dependent of the buffer length. A loop. In the worst cases, inserting a character in the beginning or deleting a character in the beginning requires copying the entire buffer.

void EditorBuffer::insertCharacter(char ch) { if ((length + 1) == capacity) expandCapacity(); for (int i = length; i > cursor; i--) { array[i] = array[i - 1]; } array[cursor] = ch; length++; cursor++; }

slide-25
SLIDE 25

An Editor Buffer Implementation I: Character Array Implementation II: Stacks Implementation III: Linked List

Assessing complexity (cont.)

Function Complexity moveCursorForward O(1) moveCursorBackward O(1) moveCursorToStart O(1) moveCursorToEnd O(1) insertCharacter O(N) deleteCharacter O(N)

  • Note. When we do a lot of insertions and deletions and the

buffer is large, it gets slow.

slide-26
SLIDE 26

An Editor Buffer Implementation I: Character Array Implementation II: Stacks Implementation III: Linked List

Outline

1

An Editor Buffer

2

Implementation I: Character Array

3

Implementation II: Stacks

4

Implementation III: Linked List

slide-27
SLIDE 27

An Editor Buffer Implementation I: Character Array Implementation II: Stacks Implementation III: Linked List

Using stacks

Idea: Breaking the buffer at the cursor boundary. Two stacks: One contains the characters that precede the cursor; One contains the characters after the cursor.

before H E L|L O L E H L O after

slide-28
SLIDE 28

An Editor Buffer Implementation I: Character Array Implementation II: Stacks Implementation III: Linked List

Using stacks

Idea: Breaking the buffer at the cursor boundary. Two stacks: One contains the characters that precede the cursor; One contains the characters after the cursor.

before H E L|L O L E H L O after

Private data representation CharStack before; CharStack after;

slide-29
SLIDE 29

An Editor Buffer Implementation I: Character Array Implementation II: Stacks Implementation III: Linked List

Implementing the methods

Figure 10-4, pp. 355-356

void EditorBuffer::moveCursorForward() { if (!after.isEmpty()) { before.push(after.pop()); } }

moveCursorBackward is similar. No loops.

slide-30
SLIDE 30

An Editor Buffer Implementation I: Character Array Implementation II: Stacks Implementation III: Linked List

Implementing the methods

Figure 10-4, pp. 355-356

void EditorBuffer::deleteCharacter() { if (!after.isEmpty()) { after.pop(); } }

insertCharacter is similar. No loops.

slide-31
SLIDE 31

An Editor Buffer Implementation I: Character Array Implementation II: Stacks Implementation III: Linked List

Implementing the methods (cont.)

moveCursorToStart requires a loop.

void EditorBuffer::moveCursorToStart() { while (!before.isEmpty() { after.push(before.pop()); } }

Worst case: When the cursor is currently at the end, we have to move (assignment) the entire buffer.

slide-32
SLIDE 32

An Editor Buffer Implementation I: Character Array Implementation II: Stacks Implementation III: Linked List

Implementing the methods (cont.)

moveCursorToStart requires a loop.

void EditorBuffer::moveCursorToStart() { while (!before.isEmpty() { after.push(before.pop()); } }

Worst case: When the cursor is currently at the end, we have to move (assignment) the entire buffer. moveCursorToEnd is similar. A loop.

slide-33
SLIDE 33

An Editor Buffer Implementation I: Character Array Implementation II: Stacks Implementation III: Linked List

Assessing complexity

Table 10-3, p. 354. Function Complexity moveCursorForward O(1) moveCursorBackward O(1) moveCursorToStart O(N) moveCursorToEnd O(N) insertCharacter O(1) deleteCharacter O(1)

slide-34
SLIDE 34

An Editor Buffer Implementation I: Character Array Implementation II: Stacks Implementation III: Linked List

Outline

1

An Editor Buffer

2

Implementation I: Character Array

3

Implementation II: Stacks

4

Implementation III: Linked List

slide-35
SLIDE 35

An Editor Buffer Implementation I: Character Array Implementation II: Stacks Implementation III: Linked List

Linked list

What is a linked list? Linked by what?

slide-36
SLIDE 36

An Editor Buffer Implementation I: Character Array Implementation II: Stacks Implementation III: Linked List

Linked list

What is a linked list? Linked by what? A list of cells linked by pointers.

slide-37
SLIDE 37

An Editor Buffer Implementation I: Character Array Implementation II: Stacks Implementation III: Linked List

Cell structure

The structure of a cell:

struct cellT { char ch; cellT *link; }

A recursive type.

slide-38
SLIDE 38

An Editor Buffer Implementation I: Character Array Implementation II: Stacks Implementation III: Linked List

Private data

struct cellT { char ch; cellT *link; }; cellT *start; cellT *cursor; Use the special pointer value NULL to signify the end of a list. Use a dummy cell at the beginning of a list. (Why?)

slide-39
SLIDE 39

An Editor Buffer Implementation I: Character Array Implementation II: Stacks Implementation III: Linked List

Constructor

EditorBuffer::EditorBuffer() { // initialize dummy cell start = new cellT; start->link = NULL; // initialize cursor cursor = start; }

cursor start A dummy cell.

slide-40
SLIDE 40

An Editor Buffer Implementation I: Character Array Implementation II: Stacks Implementation III: Linked List

Example

A|B C

C start cursor A B

The cursor pointer points to the cell containing the character that immediately precedes the cursor.

slide-41
SLIDE 41

An Editor Buffer Implementation I: Character Array Implementation II: Stacks Implementation III: Linked List

Simple things first

void EditorBuffer::moveCursorForward() { if (cursor->link != NULL) { cursor = cursor->link; } } void EditorBuffer::moveCursorToStart() { cursor = start; }

start cursor A B C

slide-42
SLIDE 42

An Editor Buffer Implementation I: Character Array Implementation II: Stacks Implementation III: Linked List

Move the cursor backward

Search from the start for the pointer pointing to the cell whose link field equals cursor.

EditorBuffer::moveCursorBackward() { cellT *cp = start; if (cursor != start) { while (cp->link != cursor) { cp = cp->link; } cursor = cp; } }

Requires a loop.

slide-43
SLIDE 43

An Editor Buffer Implementation I: Character Array Implementation II: Stacks Implementation III: Linked List

Move the cursor backward (cont.)

EditorBuffer::moveCursorBackward() { cellT *cp = start; if (cursor != start) { while (cp->link != cursor) { cp = cp->link; } cursor = cp; } }

cp start cursor

slide-44
SLIDE 44

An Editor Buffer Implementation I: Character Array Implementation II: Stacks Implementation III: Linked List

Move the cursor backward (cont.)

EditorBuffer::moveCursorBackward() { cellT *cp = start; if (cursor != start) { while (cp->link != cursor) { cp = cp->link; } cursor = cp; } }

cp start cursor

slide-45
SLIDE 45

An Editor Buffer Implementation I: Character Array Implementation II: Stacks Implementation III: Linked List

Move the cursor to the end

moveCursorToEnd is similar to moveCursorBackward.

void EditorBuffer::moveCursorToEnd() { while (cursor->link != NULL) { moveCursorForward(); } }

slide-46
SLIDE 46

An Editor Buffer Implementation I: Character Array Implementation II: Stacks Implementation III: Linked List

Two patterns

Two linked list patterns

for (cp = start; cp->link != cursor; cp = cp->link) { ... code using cp ... } for (cellT *cp = start; cp != NULL; cp = cp->link) { ... code using cp ... }

  • Example. display, p. 370.
slide-47
SLIDE 47

An Editor Buffer Implementation I: Character Array Implementation II: Stacks Implementation III: Linked List

Deletion

void EditorBuffer::deleteCharacter() { if (cursor->link != NULL) { cellT *oldcell = cursor->link; cursor->link = oldcell->link; delete oldcell; } }

C start cursor A B

slide-48
SLIDE 48

An Editor Buffer Implementation I: Character Array Implementation II: Stacks Implementation III: Linked List

Deletion (cont.)

void EditorBuffer::deleteCharacter() { if (cursor->link != NULL) { cellT *oldcell = cursor->link; cursor->link = oldcell->link; delete oldcell; } }

C start cursor A B

slide-49
SLIDE 49

An Editor Buffer Implementation I: Character Array Implementation II: Stacks Implementation III: Linked List

Deletion (cont.)

void EditorBuffer::deleteCharacter() { if (cursor->link != NULL) { cellT *oldcell = cursor->link; cursor->link = oldcell->link; delete oldcell; } }

C start cursor A

slide-50
SLIDE 50

An Editor Buffer Implementation I: Character Array Implementation II: Stacks Implementation III: Linked List

Insertion

void EditorBuffer::insertCharacter(char ch) { cellT *cp = new cellT; cp->ch = ch; cp->link = cursor->link; cursor->link = cp; cursor = cp; }

start cursor A C B cp

slide-51
SLIDE 51

An Editor Buffer Implementation I: Character Array Implementation II: Stacks Implementation III: Linked List

Insertion (cont.)

void EditorBuffer::insertCharacter(char ch) { cellT *cp = new cellT; cp->ch = ch; cp->link = cursor->link; cursor->link = cp; cursor = cp; }

start cursor A C B cp

slide-52
SLIDE 52

An Editor Buffer Implementation I: Character Array Implementation II: Stacks Implementation III: Linked List

Insertion (cont.)

void EditorBuffer::insertCharacter(char ch) { cellT *cp = new cellT; cp->ch = ch; cp->link = cursor->link; cursor->link = cp; cursor = cp; }

start cursor A C B cp

slide-53
SLIDE 53

An Editor Buffer Implementation I: Character Array Implementation II: Stacks Implementation III: Linked List

Insertion (cont.)

void EditorBuffer::insertCharacter(char ch) { cellT *cp = new cellT; cp->ch = ch; cp->link = cursor->link; cursor->link = cp; cursor = cp; }

start cursor A C B cp

slide-54
SLIDE 54

An Editor Buffer Implementation I: Character Array Implementation II: Stacks Implementation III: Linked List

Destructor

EditorBuffer::˜EditorBuffer() { cellT *cp = start; while (cp != NULL) { cellT *next = cp->link; delete cp; cp = next; } }

Note. cp points to the cell to be deleted. Save the link field of the current cell in next before deleting the cell.

slide-55
SLIDE 55

An Editor Buffer Implementation I: Character Array Implementation II: Stacks Implementation III: Linked List

Relative efficiency

Table 10-4, p. 367. Function Array Stack List moveCursorForward O(1) O(1) O(1) moveCursorBackward O(1) O(1) O(N) moveCursorToStart O(1) O(N) O(1) moveCursorToEnd O(1) O(N) O(N) insertCharacter O(N) O(1) O(1) deleteCharacter O(N) O(1) O(1)

slide-56
SLIDE 56

An Editor Buffer Implementation I: Character Array Implementation II: Stacks Implementation III: Linked List

Relative efficiency

Table 10-4, p. 367. Function Array Stack List moveCursorForward O(1) O(1) O(1) moveCursorBackward O(1) O(1) O(N) moveCursorToStart O(1) O(N) O(1) moveCursorToEnd O(1) O(N) O(N) insertCharacter O(N) O(1) O(1) deleteCharacter O(N) O(1) O(1) Question If the cursor pointer pointed to the cell containing the character immediately after the cursor, how would it affect the efficiency?

slide-57
SLIDE 57

An Editor Buffer Implementation I: Character Array Implementation II: Stacks Implementation III: Linked List

Doubly linked list

To alleviate the problem of going backwards or to the end in linked list, we can used a circular doubly linked list with a dummy cell.

start cursor

struct cellT { char ch; cellT *prev; cellT *next; }

slide-58
SLIDE 58

An Editor Buffer Implementation I: Character Array Implementation II: Stacks Implementation III: Linked List

Time-space trade-offs

In the doubly linked list implementation, all the operations have O(1) complexity, however, it takes at least nine bytes for each character, about ten times the space in the array implementation.

slide-59
SLIDE 59

An Editor Buffer Implementation I: Character Array Implementation II: Stacks Implementation III: Linked List

Time-space trade-offs

In the doubly linked list implementation, all the operations have O(1) complexity, however, it takes at least nine bytes for each character, about ten times the space in the array implementation. A hybrid method: A doubly linked list of arrays, where each array represents a line.

slide-60
SLIDE 60

An Editor Buffer Implementation I: Character Array Implementation II: Stacks Implementation III: Linked List

Time-space trade-offs

In the doubly linked list implementation, all the operations have O(1) complexity, however, it takes at least nine bytes for each character, about ten times the space in the array implementation. A hybrid method: A doubly linked list of arrays, where each array represents a line. A good design demands compromise.