EECE 330 Chapter, Fall 2011

American University of Beirut · Data Structures and Algorithms · 33 pages · Prof. Hassan Artail

All EECE 330 files
EECE 330 Chapter, Fall 2011, page 1

Stuck on a question? A tutor can walk you through it.

EECE 330 Chapter, Fall 2011, page 2 EECE 330 Chapter, Fall 2011, page 3 EECE 330 Chapter, Fall 2011, page 4 EECE 330 Chapter, Fall 2011, page 5 EECE 330 Chapter, Fall 2011, page 6 EECE 330 Chapter, Fall 2011, page 7 EECE 330 Chapter, Fall 2011, page 8 EECE 330 Chapter, Fall 2011, page 9 EECE 330 Chapter, Fall 2011, page 10

Showing the first 10 of 33 pages. Download the PDF to see all of it.

More EECE 330 files

Show the text of this chapter
EECE 330 Data Structures & Algorithms Binary Search Trees Binary Search Trees © Hassan Artail American University of Beirut Binary Search Trees BST Property: All elements stored in the left subtree of a node with value K have values < K. All elements stored in the right subtree of a node with value K have values  K. BST ADT(1) // BST implementation for the Dictionary ADT template <class Key, class Elem, class KEComp, class EEComp> class BST : public Dictionary<Key, Elem, KEComp, EEComp> {//Private Data and Helper Functions private: BinNode<Elem>* root; // Root of the BST int nodecount; // Number of nodes void clearhelp(BinNode<Elem>*); BinNode<Elem>* inserthelp(BinNode<Elem>*, const Elem&); BinNode<Elem>* deletemin(BinNode<Elem>*,BinNode<Elem>*&); BinNode<Elem>* removehelp(BinNode<Elem>*, const Key&, BinNode<Elem>*&); bool findhelp(BinNode<Elem>*, const Key&, Elem&) const; void printhelp(BinNode<Elem>*, int) const; BST ADT(2) public: BST() { root = NULL; nodecount = 0; } ~BST() { clearhelp(root); } void clear() { clearhelp(root); root = NULL; nodecount = 0; } bool insert(const Elem& e) { root = inserthelp(root, e); nodecount++; return true; } bool remove(const Key& K, Elem& e) { BinNode<Elem>* t = NULL; //we check for null below root = removehelp(root, K, t);//root may change if (t == NULL) return false; e = t->val(); // t points to a floating node now, get the nodecount--; // value that it points to before deleting it delete t; //Now, we can get rid of it return true; } Reminder • Always pass objects to functions by reference • If we are passing pointers to objects – If we are changing the pointers within the function, then pass the reference to the pointer. – Otherwise, pass the pointer itself BST ADT(3) bool removeMin(Elem& e) { // Delete node with record having minimum key value if (root == NULL) return false; // Empty BinNode<Elem>* t; // return pointer to node with minimum value root = deletemin(root, t); e = t->val(); // Get the value of t before deleting it delete t; nodecount--; return true; } bool find(const Key& K, Elem& e) const { return findhelp(root, K, e); } int size() { return nodecount; } void print() const { if (root == NULL) cout << "The BST is empty.\n"; else printhelp(root, 0); } BST Search template <class Key, class Elem, class KEComp, class EEComp> bool BST<Key, Elem, KEComp, EEComp>:: findhelp(BinNode<Elem>* subroot, const Key& K, Elem& e) const { if (subroot == NULL) return false; else if (KEComp::lt(K, subroot->val())) return findhelp(subroot->left(), K, e); else if (KEComp::gt(K, subroot->val())) return findhelp(subroot->right(), K, e); //found it. Get its value e which will traverse through the // chain of recursive calls all the way to the calling function else { e = subroot->val(); return true; } } 34 54 77 30 25 28 27 16 29 BST Insert (1) BST Insert (2) template <class Key, class Elem, class KEComp, class EEComp> BinNode<Elem>* BST<Key,Elem,KEComp,EEComp>:: inserthelp(BinNode<Elem>* subroot, const Elem& val) { if (subroot == NULL) // Empty: create node // the returned node becomes an argument to setLeft or setRight return new BinNodePtr<Elem>(val,NULL,NULL); // application of EEComp: comparing node values (records) if (EEComp::lt(val, subroot->val())) subroot->setLeft(inserthelp(subroot->left(), val)); else subroot->setRight( inserthelp(subroot->right(), val)); // Return subtree with node inserted return subroot; } 34 54 77 30 25 28 27 16 29 Remove Minimum Value template <class Key, class Elem, class KEComp, class EEComp> BinNode<Elem>* BST<Key, Elem, KEComp, EEComp>:: deletemin(BinNode<Elem>* subroot, BinNode<Elem>*& min) { if (subroot->left() == NULL) { min = subroot; return subroot->right(); } else { // Minimum value is always found as the left-most node subroot->setLeft( deletemin(subroot->left(), min)); return subroot; // in the last step into the recursion, the original subroot will be returned } } 20 9 5 5 10 subroot BST Remove (1) BST Remove (2) template <class Key, class Elem, class KEComp, class EEComp> BinNode<Elem>* BST<Key,Elem,KEComp,EEComp>:: removehelp(BinNode<Elem>* subroot, const Key& K, BinNode<Elem>*& t) { //t is the node to remove (if we find it using K) if (subroot == NULL) return NULL; else if (KEComp::lt(K, subroot->val())) subroot->setLeft( removehelp(subroot->left(), K, t)); else if (KEComp::gt(K, subroot->val())) subroot->setRight( removehelp(subroot->right(), K, t)); BST Remove (2) else { // Found it: remove it BinNode<Elem>* temp; t = subroot; if (subroot->left() == NULL) //replace it with subroot = subroot->right();//its right child else if (subroot->right() == NULL)//replace it subroot = subroot->left(); //with its left child else { // Both children are non-empty; look for min in right subtree deletemin(subroot->right(), temp); Elem te = subroot->val(); subroot->setVal(temp->val()); temp->setVal(te); t = temp; } } return subroot; } Cost of BST Operations Find: O (log n) in a close-to-balanced tree Insert: O (log n) if nodes arrive randomly O (n) if nodes arrive in increasing value Delete: 2O(log n) involves finding the node and then replacing it with the node with minimum in the right sub-tree Array Implementation Node 0 1 2 3 4 5 6 7 8 9 10 11 Parent -- 0 0 1 1 2 2 3 3 4 4 5 Left Child 1 3 5 7 9 11 -- -- -- -- -- -- Right Child 2 4 6 8 10 -- -- -- -- -- -- -- Left Sibling -- -- 1 -- 3 -- 5 -- 7 -- 9 -- Right Sibling -- 2 -- 4 -- 6 -- 8 -- 10 -- -- Array Implementation Parent (r) = (r-1)/2 if r  0 Leftchild(r) = 2r+1 if 2r+1 < n Rightchild(r) = 2r+2 if 2r+2 < n Leftsibling(r) = r-1 if r is even Rightsibling(r) = r+1 if r is odd and r+1 < n Heaps Heap: Complete binary tree with the heap property: • Min-heap: All values in parent are less than child values. • Max-heap: All values in parent are greater than child values. The values are partially ordered. Heap representation: Normally the array- based complete binary tree representation. Heap ADT template<class Elem,class Comp> class maxheap { private: Elem* Heap; // Pointer to the heap array int size; // Maximum size of the heap int n; // Number of elems now in heap void siftdown(int); // Put element in place public: maxheap(Elem* h, int num, int max); int heapsize() const; bool isLeaf(int pos) const; int leftchild(int pos) const; int rightchild(int pos) const; int parent(int pos) const; bool insert(const Elem&); bool removemax(Elem&); bool remove(int, Elem&); void buildHeap(); }; Siftdown For fast heap construction: • Work from high end of array to low end. • Call Call siftdown siftdown for each item for each item, except leaf nodes. template <class Elem, class Comp> void maxheap<Elem,Comp>:: siftdown(int pos) { while (!isLeaf(pos)) { int j = leftchild(pos); int rc = rightchild(pos); //get index of child with maximum value if ((rc<n) && Comp::lt(Heap[j],Heap[rc])) j = rc; //j is always made to be the index of greater child if (!Comp::lt(Heap[pos], Heap[j])) return; swap(Heap, pos, j); pos = j; //position becomes the index of child with } //greater value } 11 10 9 8 7 6 5 4 3 2 1 0 12 Value -- -- -- -- -- -- 12 10 8 6 4 2 Right Child -- -- -- -- -- -- 11 9 7 5 3 1 Left Child 5 4 4 3 3 2 2 1 1 0 0 -- Parent Node Position -- -- 5 Leaf Nodes 50 8 16 10 2 70 66 40 13 4 18 20 3 18 66 2 50 40 13 10 70 8 16 3 4 20 50 8 16 10 2 70 66 40 13 4 18 20 3 18 66 2 50 40 13 10 70 8 16 3 4 20 50 8 16 10 2 70 66 40 13 20 18 4 3 18 66 2 50 40 13 10 70 8 16 3 20 4 50 8 16 10 2 70 66 40 13 20 18 4 3 18 66 2 50 40 13 10 70 8 16 3 20 4 50 8 16 66 2 70 10 40 13 20 18 4 3 18 10 2 50 40 13 66 70 8 16 3 20 4 50 8 16 66 2 70 10 40 13 20 18 4 3 18 10 2 50 40 13 66 70 8 16 3 20 4 8 50 16 66 2 70 10 40 13 20 18 4 3 18 10 2 40 13 8 66 50 70 16 3 20 4 8 50 16 66 2 70 10 40 13 20 18 4 3 18 10 2 40 13 8 66 50 70 16 3 20 4 8 50 70 66 2 16 10 40 13 20 18 4 3 18 10 2 40 13 8 66 50 16 70 3 20 4 8 50 70 66 2 16 10 40 13 20 18 4 3 18 10 2 40 13 8 66 50 16 70 3 20 4 8 50 70 66 2 40 10 16 13 20 18 4 3 18 10 2 16 13 8 66 50 40 70 3 20 4 8 50 70 66 2 40 10 16 13 20 18 4 3 18 10 2 16 13 8 66 50 40 70 3 20 4 8 50 3 66 2 40 10 16 13 20 18 4 70 18 10 2 16 13 8 66 50 40 3 70 20 4 8 50 3 66 2 40 10 16 13 20 18 4 70 18 10 2 16 13 8 66 50 40 3 70 20 4 8 50 66 3 2 40 10 16 13 20 18 4 70 18 10 2 16 13 8 3 50 40 66 70 20 4 8 50 66 3 2 40 10 16 13 20 18 4 70 18 10 2 16 13 8 3 50 40 66 70 20 4 8 50 66 10 2 40 3 16 13 20 18 4 70 18 3 2 16 13 8 10 50 40 66 70 20 4 8 50 66 10 2 40 3 16 13 20 18 4 70 18 10 2 3 16 8 13 50 40 66 70 20 4 Buildheap Cost Cost for heap construction: log n  (i - 1) n/2i  n. i=1 Insert template <class Elem, class Comp> bool maxheap<Elem, Comp>:: insert (const Elem& it) { if (n>=size) return false; // Heap full Heap[n++] = it; // put the value at the end for (i=floor(n/2.0)-1; i>=0; i--) siftdown(i); // This restores the order return true; } Remove template <class Elem, class Comp> bool maxheap<Elem, Comp>:: remove (int i, Elem& it) { if (i>=n || n==0) return false; // invalid index or Heap empty swap(Heap, i, --n); // Swap max with end if (n != 0) siftdown(i); // This restores the order it = Heap[n]; // Return max value return true; } Remove Max Value template <class Elem, class Comp> bool maxheap<Elem, Comp>:: removemax(Elem& it) { if (n == 0) return false; // Heap empty swap(Heap, 0, --n); // Swap max with end if (n != 0) siftdown(0); // This restores the order it = Heap[n]; // Return max value return true; } Priority Queues (1) A priority queue stores objects, and on request releases the object with greatest value. Example: Scheduling jobs in a multi-tasking operating system. The priority of a job may change, requiring some reordering of the jobs. Implementation: Use a heap to store the priority queue. Priority Queues (2) To support priority reordering (change the priority of a certain item), we may need to know the index of the object in question, and then remove it and reinsert it. template <class Elem, class Comp> bool maxheap<Elem, Comp>::remove(int pos, Elem& it) { if ((pos < 0) || (pos >= n)) return false; swap(Heap, pos, --n); //swap with last value while ((pos != 0) && (Comp::gt(Heap[pos], Heap[parent(pos)]))) swap(Heap, pos, parent(pos)); siftdown(pos); //restore order if needed it = Heap[n]; return true; } Huffman Coding Trees ASCII codes: 8 bits per character. • Fixed-length coding. Can take advantage of relative frequency (weight) of letters to save space. • Variable-length coding Assign shorter codes to characters that are used more commonly, and thus save space  Compression Z K F C U D L E 2 7 24 32 37 42 42 120 Huffman Coding Trees • Huffman code for each letter is derived from a full binary tree called Huffman coding tree. • Each leaf of the tree corresponds to a letter  weight of the leaf node is the weight (frequency) of its associated letter. • Goal is to build a tree with the minimum external path weight (MEPW). – For a leaf, the MEPW is its weight times its depth. – The binary tree with the MEPW is the one with the minimum sum of weighted path lengths for the given set of leaves. – A letter with high weight should have low depth, so it counts the least against the total path weight  another letter should be pushed deeper into the tree if it has less weight Building a Huffman Coding Tree 1. Having a string of n letters, 2. Create a collection of n initial Huffman trees, each of which is a single leaf node containing one of the letters. 3. Put the n partial trees in a list in ascending order by weight. 4. Remove the first two trees 5. Join these two trees to create a new one whose root has the two trees as children and whose weight is the sum of weights of the two trees 6. Put this tree back in the list in the correct place necessary to preserve the order of the list 7. Repeat steps 4 through 6 until all of the partial trees have been combined into one. Huffman Tree Construction for 8 selected letters Huffman Tree Construction (2) Assigning Codes Letter Freq Code Bits C 32 D 42 E 120 K 7 L 42 M 24 U 37 Z 2 1110 4 1111 3 0 1 111101 6 110 3 11111 5 11112 3 111100 6 Assigning and Using Huffman Codes • Once the tree has been constructed, we need to assign codes to individual letters. • Beginning at the root, we assign either a ‘0’ or a ‘1’ to each edge in the tree: ‘0’ to the left child and ‘1’ to the right child. • The Huffman code for a letter is a binary number determined by the path from the root to the leaf corresponding to that letter. • Decoding the message is done by looking at the bits in the coded string from left to right until a letter is decoded. • This is done by using the Huffman tree in a reverse process compared to that used in the generation process. • Decoding the bit string begins at the root of the tree • Take branches depending on the bit value: left for ‘0’ and right for ‘1’ until reaching a leaf node. • This leaf contains the first character in the message. • Next, process the following bit in the code starting at the new root to begin the next character Decoding a code • Consider the code string 1011001110111101. • Begin at the root, taking a right branch, left branch, right branch (101)  we reach a leaf corresponding to the letter D. – The remaining code is 1001110111101 • Begin at the root, taking a right branch, left branch, left branch (100)  we reach a leaf corresponding to the letter U. – The remaining code is 1110111101 • Begin at the root, taking a right branch, right branch, right branch, left branch (1110)  we reach a leaf corresponding to the letter C. – The remaining code is 111101 • Begin at the root, taking a right branch, right branch, right branch, right branch, left branch, and then a right branch (111101)  we reach a leaf corresponding to the letter K. – The code is exhausted • The decoded message is “DUCK”