ECE 250 Algorithms and Data Structures Douglas Wilhelm Harder, M.Math. LEL Department of Electrical and Computer Engineering University of Waterloo Waterloo,

Slides:



Advertisements
Similar presentations
ECE 250 Algorithms and Data Structures Douglas Wilhelm Harder, M.Math. LEL Department of Electrical and Computer Engineering University of Waterloo Waterloo,
Advertisements

ECE 250 Algorithms and Data Structures Douglas Wilhelm Harder, M.Math. LEL Department of Electrical and Computer Engineering University of Waterloo Waterloo,
ECE 250 Algorithms and Data Structures Douglas Wilhelm Harder, M.Math. LEL Department of Electrical and Computer Engineering University of Waterloo Waterloo,
ECE 250 Algorithms and Data Structures Douglas Wilhelm Harder, M.Math. LEL Department of Electrical and Computer Engineering University of Waterloo Waterloo,
ECE 250 Algorithms and Data Structures Douglas Wilhelm Harder, M.Math. LEL Department of Electrical and Computer Engineering University of Waterloo Waterloo,
ECE 250 Algorithms and Data Structures Douglas Wilhelm Harder, M.Math. LEL Department of Electrical and Computer Engineering University of Waterloo Waterloo,
ECE 250 Algorithms and Data Structures Douglas Wilhelm Harder, M.Math. LEL Department of Electrical and Computer Engineering University of Waterloo Waterloo,
CS 315 March 24 Goals: Heap (Chapter 6) priority queue definition of a heap Algorithms for Insert DeleteMin percolate-down Build-heap.
CS 206 Introduction to Computer Science II 11 / 04 / 2009 Instructor: Michael Eckmann.
ECE 250 Algorithms and Data Structures Douglas Wilhelm Harder, M.Math. LEL Department of Electrical and Computer Engineering University of Waterloo Waterloo,
ECE 250 Algorithms and Data Structures Douglas Wilhelm Harder, M.Math. LEL Department of Electrical and Computer Engineering University of Waterloo Waterloo,
ECE 250 Algorithms and Data Structures Douglas Wilhelm Harder, M.Math. LEL Department of Electrical and Computer Engineering University of Waterloo Waterloo,
More Trees COL 106 Amit Kumar and Shweta Agrawal Most slides courtesy : Douglas Wilhelm Harder, MMath, UWaterloo
ECE 250 Algorithms and Data Structures Douglas Wilhelm Harder, M.Math. LEL Department of Electrical and Computer Engineering University of Waterloo Waterloo,
ECE 250 Algorithms and Data Structures Douglas Wilhelm Harder, M.Math. LEL Department of Electrical and Computer Engineering University of Waterloo Waterloo,
ECE 250 Algorithms and Data Structures Douglas Wilhelm Harder, M.Math. LEL Department of Electrical and Computer Engineering University of Waterloo Waterloo,
ECE 250 Algorithms and Data Structures Douglas Wilhelm Harder, M.Math. LEL Department of Electrical and Computer Engineering University of Waterloo Waterloo,
ECE 250 Algorithms and Data Structures Douglas Wilhelm Harder, M.Math. LEL Department of Electrical and Computer Engineering University of Waterloo Waterloo,
1 HEAPS & PRIORITY QUEUES Array and Tree implementations.
ECE 250 Algorithms and Data Structures Douglas Wilhelm Harder, M.Math. LEL Department of Electrical and Computer Engineering University of Waterloo Waterloo,
Proof by Induction.
CS 1031 Tree Traversal Techniques; Heaps Tree Traversal Concept Tree Traversal Techniques: Preorder, Inorder, Postorder Full Trees Almost Complete Trees.
ECE 250 Algorithms and Data Structures Douglas Wilhelm Harder, M.Math. LEL Department of Electrical and Computer Engineering University of Waterloo Waterloo,
ECE 250 Algorithms and Data Structures Douglas Wilhelm Harder, M.Math. LEL Department of Electrical and Computer Engineering University of Waterloo Waterloo,
Binary Numbers Douglas Wilhelm Harder Department of Electrical and Computer Engineering University of Waterloo Copyright © 2007 by Douglas Wilhelm Harder.
ECE 250 Algorithms and Data Structures Douglas Wilhelm Harder, M.Math. LEL Department of Electrical and Computer Engineering University of Waterloo Waterloo,
Priority Queues and Binary Heaps Chapter Trees Some animals are more equal than others A queue is a FIFO data structure the first element.
ECE 250 Algorithms and Data Structures Douglas Wilhelm Harder, M.Math. LEL Department of Electrical and Computer Engineering University of Waterloo Waterloo,
ECE 250 Algorithms and Data Structures Douglas Wilhelm Harder, M.Math. LEL Department of Electrical and Computer Engineering University of Waterloo Waterloo,
Chapter 21 Priority Queue: Binary Heap Saurav Karmakar.
P p Chapter 10 has several programming projects, including a project that uses heaps. p p This presentation shows you what a heap is, and demonstrates.
ECE 250 Algorithms and Data Structures Douglas Wilhelm Harder, M.Math. LEL Department of Electrical and Computer Engineering University of Waterloo Waterloo,
ECE 250 Algorithms and Data Structures Douglas Wilhelm Harder, M.Math. LEL Department of Electrical and Computer Engineering University of Waterloo Waterloo,
ECE 250 Algorithms and Data Structures Douglas Wilhelm Harder, M.Math. LEL Department of Electrical and Computer Engineering University of Waterloo Waterloo,
Douglas Wilhelm Harder, M.Math. LEL Department of Electrical and Computer Engineering University of Waterloo Waterloo, Ontario, Canada ece.uwaterloo.ca.
ECE 250 Algorithms and Data Structures Douglas Wilhelm Harder, M.Math. LEL Department of Electrical and Computer Engineering University of Waterloo Waterloo,
1 Joe Meehean.  We wanted a data structure that gave us... the smallest item then the next smallest then the next and so on…  This ADT is called a priority.
ECE 250 Algorithms and Data Structures Douglas Wilhelm Harder, M.Math. LEL Department of Electrical and Computer Engineering University of Waterloo Waterloo,
Priority Queues and Heaps. October 2004John Edgar2  A queue should implement at least the first two of these operations:  insert – insert item at the.
AVL Trees 1. 2 Outline Background Define balance Maintaining balance within a tree –AVL trees –Difference of heights –Rotations to maintain balance.
ECE 250 Algorithms and Data Structures Douglas Wilhelm Harder, M.Math. LEL Department of Electrical and Computer Engineering University of Waterloo Waterloo,
Douglas Wilhelm Harder, M.Math. LEL Department of Electrical and Computer Engineering University of Waterloo Waterloo, Ontario, Canada ece.uwaterloo.ca.
Heapsort. What is a “heap”? Definitions of heap: 1.A large area of memory from which the programmer can allocate blocks as needed, and deallocate them.
Week 10 - Friday.  What did we talk about last time?  Graph representations  Adjacency matrix  Adjacency lists  Depth first search.
ECE 250 Algorithms and Data Structures Douglas Wilhelm Harder, M.Math. LEL Department of Electrical and Computer Engineering University of Waterloo Waterloo,
ECE 250 Algorithms and Data Structures Douglas Wilhelm Harder, M.Math. LEL Department of Electrical and Computer Engineering University of Waterloo Waterloo,
Tree Data Structures. Heaps for searching Search in a heap? Search in a heap? Would have to look at root Would have to look at root If search item smaller.
HEAPS. Review: what are the requirements of the abstract data type: priority queue? Quick removal of item with highest priority (highest or lowest key.
Internal and External Sorting External Searching
AVL Trees and Heaps. AVL Trees So far balancing the tree was done globally Basically every node was involved in the balance operation Tree balancing can.
Week 15 – Wednesday.  What did we talk about last time?  Review up to Exam 1.
CS 367 Introduction to Data Structures Lecture 8.
Priority Queues and Heaps Data Structures and Algorithms CS 244 Brent M. Dingle, Ph.D. Department of Mathematics, Statistics, and Computer Science University.
ECE 250 Algorithms and Data Structures Douglas Wilhelm Harder, M.Math. LEL Department of Electrical and Computer Engineering University of Waterloo Waterloo,
ECE 250 Algorithms and Data Structures Douglas Wilhelm Harder, M.Math. LEL Department of Electrical and Computer Engineering University of Waterloo Waterloo,
1 The tree data structure Outline In this topic, we will cover: –Definition of a tree data structure and its components –Concepts of: Root, internal, and.
2 Binary Heaps What if we’re mostly concerned with finding the most relevant data?  A binary heap is a binary tree (2 or fewer subtrees for each node)
ECE 250 Algorithms and Data Structures Douglas Wilhelm Harder, M.Math. LEL Department of Electrical and Computer Engineering University of Waterloo Waterloo,
Course: Programming II - Abstract Data Types HeapsSlide Number 1 The ADT Heap So far we have seen the following sorting types : 1) Linked List sort by.
ECE 250 Algorithms and Data Structures Douglas Wilhelm Harder, M.Math. LEL Department of Electrical and Computer Engineering University of Waterloo Waterloo,
1 N -ary trees This topic quickly looks at a generalization of a binary tree, where each node has up to N children –Definition –Perfect N -ary trees –Complete.
ECE 250 Algorithms and Data Structures Douglas Wilhelm Harder, M.Math. LEL Department of Electrical and Computer Engineering University of Waterloo Waterloo,
1 Complete binary trees Outline Introducing complete binary trees –Background –Definitions –Examples –Logarithmic height –Array storage.
Outline In this topic, we will: Define a binary min-heap
Outline In this topic we will look at:
Open Addressing: Quadratic Probing
AVL Trees.
Multiway Search Trees.
Outline In this topic we will look at quicksort:
Heaps & Multi-way Search Trees
Presentation transcript:

ECE 250 Algorithms and Data Structures Douglas Wilhelm Harder, M.Math. LEL Department of Electrical and Computer Engineering University of Waterloo Waterloo, Ontario, Canada ece.uwaterloo.ca © by Douglas Wilhelm Harder. Some rights reserved. Douglas Wilhelm Harder, M.Math. LEL Department of Electrical and Computer Engineering University of Waterloo Waterloo, Ontario, Canada ece.uwaterloo.ca © by Douglas Wilhelm Harder. Some rights reserved. Binary heaps

2 Outline In this topic, we will: –Define a binary min-heap –Look at some examples –Operations on heaps: Top Pop Push –An array representation of heaps –Define a binary max-heap –Using binary heaps as priority queues

3 Binary heaps Definition A non-empty binary tree is a min-heap if –The key associated with the root is less than or equal to the keys associated with either of the sub-trees (if any) –Both of the sub-trees (if any) are also binary min-heaps From this definition: –A single node is a min-heap –All keys in either sub-tree are greater than the root key 7.2

4 Binary heaps Definition Important: THERE IS NO OTHER RELATIONSHIP BETWEEN THE ELEMENTS IN THE TWO SUBTREES Failing to understand this is the greatest mistake a student makes 7.2

5 Binary heaps Example This is a binary min-heap: 7.2

6 Binary heaps Example Adding colour, we observe –The left subtree has the smallest (7) and the largest (89) objects –No relationship between items with similar priority 7.2

7 Binary heaps Operations We will consider three operations: –Top –Pop –Push 7.2.1

8 Binary heaps Example We can find the top object in  (1) time:

9 Binary heaps Pop To remove the minimum object: –Promote the node of the sub-tree which has the least value –Recurs down the sub-tree from which we promoted the least value

10 Binary heaps Pop Using our example, we remove 3:

11 Binary heaps Pop We promote 7 (the minimum of 7 and 12) to the root:

12 Binary heaps Pop In the left sub-tree, we promote 9:

13 Binary heaps Pop Recursively, we promote 19:

14 Binary heaps Pop Finally, 55 is a leaf node, so we promote it and delete the leaf

15 Binary heaps Pop Repeating this operation again, we can remove 7:

16 Binary heaps Pop If we remove 9, we must now promote from the right sub-tree:

17 Binary heaps Push Inserting into a heap may be done either: –At a leaf (move it up if it is smaller than the parent) –At the root (insert the larger object into one of the subtrees) We will use the first approach with binary heaps –Other heaps use the second

18 Binary heaps Push Inserting 17 into the last heap –Select an arbitrary node to insert a new leaf node:

19 Binary heaps Push The node 17 is less than the node 32, so we swap them

20 Binary heaps Push The node 17 is less than the node 31; swap them

21 Binary heaps Push The node 17 is less than the node 19; swap them

22 Binary heaps Push The node 17 is greater than 12 so we are finished

23 Binary heaps Push Observation: both the left and right subtrees of 19 were greater than 19, thus we are guaranteed that we don’t have to send the new node down This process is called percolation, that is, the lighter (smaller) objects move up from the bottom of the min-heap

24 Binary heaps Implementations With binary search trees, we introduced the concept of balance From this, we looked at: –AVL Trees –B-Trees –Red-black Trees (not course material) How can we determine where to insert so as to keep balance? 7.2.2

25 Binary heaps Implementations There are multiple means of keeping balance with binary heaps: –Complete binary trees –Leftist heaps –Skew heaps We will look at using complete binary trees –In has optimal memory characteristics but sub-optimal run-time characteristics 7.2.2

26 Binary heaps Complete Trees By using complete binary trees, we will be able to maintain, with minimal effort, the complete tree structure We have already seen –It is easy to store a complete tree as an array If we can store a heap of size n as an array of size  (n), this would be great! 7.2.2

27 Binary heaps Complete Trees For example, the previous heap may be represented as the following (non-unique!) complete tree: 7.2.2

28 Binary heaps Complete Trees: Push If we insert into a complete tree, we need only place the new node as a leaf node in the appropriate location and percolate up 7.2.2

29 Binary heaps Complete Trees: Push For example, push 25: 7.2.2

30 Binary heaps Complete Trees: Push We have to percolate 25 up into its appropriate location –The resulting heap is still a complete tree 7.2.2

31 Binary heaps Complete Trees: Pop Suppose we want to pop the top entry:

32 Binary heaps Complete Trees: Pop Percolating up creates a hole leading to a non-complete tree 7.2.2

33 Binary heaps Complete Trees: Pop Alternatively, copy the last entry in the heap to the root 7.2.2

34 Binary heaps Complete Trees: Pop Now, percolate 36 down swapping it with the smallest of its children –We halt when both children are larger 7.2.2

35 Binary heaps Complete Trees: Pop The resulting tree is now still a complete tree: 7.2.2

36 Binary heaps Complete Trees: Pop Again, popping 15, copy up the last entry:

37 Binary heaps Complete Trees: Pop This time, it gets percolated down to the point where it has no children 7.2.2

38 Binary heaps Complete Trees: Pop In popping 17, 53 is moved to the top 7.2.2

39 Binary heaps Complete Trees: Pop And percolated down, again to the deepest level 7.2.2

40 Binary heaps Complete Trees: Pop Popping 19 copies up

41 Binary heaps Complete Trees: Pop Which is then percolated down to the second deepest level 7.2.2

42 Binary heaps Complete Tree Therefore, we can maintain the complete-tree shape of a heap We may store a complete tree using an array: –A complete tree is filled in breadth-first traversal order –The array is filled using breadth-first traversal 7.2.3

43 Binary heaps Array Implementation For the heap a breadth-first traversal yields:

44 Binary heaps Array Implementation Recall that If we associate an index–starting at 1–with each entry in the breadth-first traversal, we get: Given the entry at index k, it follows that: –The parent of node is a k/2 parent = k >> 1; –the children are at 2k and 2k + 1 left_child = k << 1; right_child = left_child | 1; Cost (trivial): start array at position 1 instead of position

45 Binary heaps Array Implementation The children of 15 are 17 and 32:

46 Binary heaps Array Implementation The children of 17 are 25 and 19:

47 Binary heaps The children of 32 are 41 and 36: Array Implementation

48 Binary heaps Array Implementation The children of 25 are 33 and 55:

49 Binary heaps Array Implementation If the heap-as-array has count entries, then the next empty node in the corresponding complete tree is at location posn = count + 1 We compare the item at location posn with the item at posn/2 If they are out of order –Swap them, set posn /= 2 and repeat

50 Binary heaps Consider the following heap, both as a tree and in its array representation Array Implementation

51 Binary heaps Array Implementation: Push Inserting 26 requires no changes

52 Binary heaps Array Implementation: Push Inserting 8 requires a few percolations: –Swap 8 and

53 Binary heaps Array Implementation: Push Swap 8 and

54 Binary heaps Array Implementation: Push At this point, it is greater than its parent, so we are finished

55 Binary heaps As before, popping the top has us copy the last entry to the top Array Implementation: Pop

56 Binary heaps Array Implementation: Pop Instead, consider this strategy: –Copy the last object, 23, to the root

57 Binary heaps Array Implementation: Pop Now percolate down Compare Node 1 with its children: Nodes 2 and 3 –Swap 23 and

58 Binary heaps Array Implementation: Pop Compare Node 2 with its children: Nodes 4 and 5 –Swap 23 and

59 Binary heaps Array Implementation: Pop Compare Node 4 with its children: Nodes 8 and 9 –Swap 23 and

60 Binary heaps Array Implementation: Pop The children of Node 8 are beyond the end of the array: –Stop

61 Binary heaps Array Implementation: Pop The result is a binary min-heap

62 Binary heaps Array Implementation: Pop Dequeuing the minimum again: –Copy 26 to the root

63 Binary heaps Array Implementation: Pop Compare Node 1 with its children: Nodes 2 and 3 –Swap 26 and

64 Binary heaps Array Implementation: Pop Compare Node 3 with its children: Nodes 6 and 7 –Swap 26 and

65 Binary heaps Array Implementation: Pop The children of Node 6, Nodes 12 and 13 are unoccupied –Currently, count ==

66 Binary heaps Array Implementation: Pop The result is a min-heap

67 Binary heaps Array Implementation: Pop Dequeuing the minimum a third time: –Copy 15 to the root

68 Binary heaps Array Implementation: Pop Compare Node 1 with its children: Nodes 2 and 3 –Swap 15 and

69 Binary heaps Array Implementation: Pop Compare Node 2 with its children: Nodes 4 and 5 –Swap 15 and

70 Binary heaps Array Implementation: Pop Compare Node 4 with its children: Nodes 8 and 9 –15 < 23 and 15 < 25 so stop

71 Binary heaps Array Implementation: Pop The result is a properly formed binary min-heap

72 Binary heaps Array Implementation: Pop After all our modifications, the final heap is

73 Binary heaps Run-time Analysis Accessing the top object is  (1) Popping the top object is O(ln(n)) –We copy something that is already in the lowest depth—it will likely be moved back to the lowest depth How about push? 7.2.4

74 Binary heaps Run-time Analysis If we are inserting an object less than the root (at the front), then the run time will be  (ln(n)) If we insert at the back (greater than any object) then the run time will be  (1) How about an arbitrary insertion? –It will be O(ln(n)) ? Could the average be less? 7.2.4

75 Binary heaps Run-time Analysis With each percolation, it will move an object past half of the remaining entries in the tree –Therefore after one percolation, it will probably be past half of the entries, and therefore on average will require no more percolations Therefore, we have an average run time of  (1) 7.2.4

76 Binary heaps Run-time Analysis An arbitrary removal requires that all entries in the heap be checked: O(n) A removal of the largest object in the heap still requires all leaf nodes to be checked – there are approximately n/2 leaf nodes: O(n) 7.2.4

77 Binary heaps Run-time Analysis Thus, our grid of run times is given by: 7.2.4

78 Binary heaps Run-time Analysis Some observations: –Continuously inserting at the front of the heap (i.e., the new object being pushed is less than everything in the heap) causes the run-time to drop to O(ln(n)) –If the objects are coming in order of priority, use a regular queue with swapping –Merging two binary heaps of size n is a  (n) operation 7.2.4

79 Binary heaps Run-time Analysis Other heaps have better run-time characteristics –Leftist, skew, binomial and Fibonacci heaps all use a node-based implementation requiring  (n) additional memory –For Fibonacci heaps, the run-time of all operations (including merging two Fibonacci heaps) except pop are  (1) 7.2.4

80 Binary heaps Binary Max Heaps A binary max-heap is identical to a binary min-heap except that the parent is always larger than either of the children For example, the same data as before stored as a max-heap yields 7.2.5

81 Binary heaps Example Here we have a max-heap of presents under a red-green tree:

82 Binary heaps Memory allocation and pointer arithmetic Do we really have to allocate one additional memory location for a binary tree-as-heap? Type *heap_array = new Type[capacity() + 1]; Could we not just allocate one less memory and point to the previous location in memory heap_array

83 Binary heaps Memory allocation and pointer arithmetic To do this, we must understand pointer arithmetic: int *ptr = new int[5] = {1, 23, 45, 67, 89}; std::cout << ptr << std::endl; std::cout << *ptr << std::endl; 00d3a26000d3a26400d3a26800d3a26B00d3a D ptr What is the output of? std::cout << (ptr + 1) << std::endl; std::cout << *(ptr + 1) << std::endl;

84 Binary heaps Memory allocation and pointer arithmetic Just adding one to the address would be, in almost all cases, useless –Assuming big endian, this would have a value 256 –If this was little endian, it would be even more bizarre… 00d3a26000d3a26400d3a26800d3a26B00d3a D ptr What is the output of? std::cout << (ptr + 1) << std::endl; std::cout << *(ptr + 1) << std::endl;

85 Binary heaps Memory allocation and pointer arithmetic Instead, C and C++ add as many bytes as the size of the object being pointed to –In the cases of int, sizeof( int ) == 4 on most 32-bit machines –The output is 23 00d3a26000d3a26400d3a26800d3a26B00d3a D ptr What is the output of? std::cout << (ptr + 1) << std::endl; std::cout << *(ptr + 1) << std::endl;

86 Binary heaps Memory allocation and pointer arithmetic Essentially, these two statements are identical: std::cout << ptr[i] << std::endl; std::cout << *(ptr + i) << std::endl; Now you can do the following: Type *tmp = new Type[capacity()]; Type *heap_array = tmp - 1; Now, heap_array[1]; and tmp[0]; both point to the same memory location 00d3a26000d3a26400d3a26800d3a26B00d3a D tmp heap_array

87 Binary heaps Memory allocation and pointer arithmetic Issues: –Never access or modify the contents of heap_array[0] –When you deallocate memory, you must point to the original address returned by new : delete [] (heap_array + 1); –Pointer arithmetic is not for the faint of heart but it is fun; for example: int array[N]; int *ptr = array; // Print all the entries of the array for ( int i = 0; i < N; ++i ) { std::cout << *(ptr++) << std::endl; }

88 Binary heaps Priority Queues Now, does using a heap ensure that that object in the heap which: –has the highest priority, and –of that highest priority, has been in the heap the longest Consider inserting seven objects, all of the same priority (colour indicates order): 2, 2, 2, 2, 2, 2,

89 Binary heaps Priority Queues Whatever algorithm we use for promoting must ensure that the first object remains in the root position –Thus, we must use an insertion technique where we only percolate up if the priority is lower The result: Challenge: –Come up with an algorithm which removes all seven objects in the original order 7.2.6

90 Binary heaps Lexicographical Ordering A better solution is to modify the priority: –Track the number of insertions with a counter k (initially 0) –For each insertion with priority n, create a hybrid priority (n, k) where: (n 1, k 1 ) < (n 2, k 2 ) if n 1 < n 2 or ( n 1 = n 2 and k 1 < k 2 ) 7.2.6

91 Binary heaps Priority Queues Removing the objects would be in the following order: 7.2.6

92 Binary heaps Priority Queues Popped: 2 –First, (2,1) < (2, 2) and (2, 3) < (2, 4) 7.2.6

93 Binary heaps Priority Queues Removing the objects would be in the following order: 7.2.6

94 Binary heaps Priority Queues Removing the objects would be in the following order: 7.2.6

95 Binary heaps Priority Queues Removing the objects would be in the following order: 7.2.6

96 Binary heaps Priority Queues Removing the objects would be in the following order: 7.2.6

97 Binary heaps Summary In this talk, we have: –Discussed binary heaps –Looked at an implementation using arrays –Analyzed the run time: Head  (1) Push  (1) average Pop O(ln(n)) –Discussed implementing priority queues using binary heaps –The use of a lexicographical ordering 7.2.6

98 Binary heaps References [1]Donald E. Knuth, The Art of Computer Programming, Volume 3: Sorting and Searching, 2 nd Ed., Addison Wesley, 1998, §7.2.3, p.144. [2]Cormen, Leiserson, and Rivest, Introduction to Algorithms, McGraw Hill, 1990, §7.1-3, p [3]Weiss, Data Structures and Algorithm Analysis in C++, 3 rd Ed., Addison Wesley, §6.3, p

99 Binary heaps Usage Notes These slides are made publicly available on the web for anyone to use If you choose to use them, or a part thereof, for a course at another institution, I ask only three things: –that you inform me that you are using the slides, –that you acknowledge my work, and –that you alert me of any mistakes which I made or changes which you make, and allow me the option of incorporating such changes (with an acknowledgment) in my set of slides Sincerely, Douglas Wilhelm Harder, MMath