#ifndef HUFFMAN_TREE_H #define HUFFMAN_TREE_H // Oldham, Jeffrey D. // 2000Apr26 // CS1321 // Huffman Tree Class // This class creates Huffman trees and supports input and output on // them. // ASSUMPTIONS: // Huffman trees are never empty. // Use of ASCII encoding. // CHAR_BIT bits on both machine to encode and machine to decode. // The Huffman tree is represented using prefix notation with two // characters (c1,c2) per node. If c1 == 'l', then the next character // represents a leaf. If c1 == 'i', then the next character // represents an internal node. The tree must not be empty. #include #include // has EXIT_SUCCESS #include "tree.h" #include #include // has doubly-linked lists #include // has min_element class HuffmanTree { public: typedef unsigned long ul; typedef pair freqChar; typedef Tree tfc; // Create an empty Huffman tree. HuffmanTree(void) {} // Create a Huffman tree using the given frequency-char pairs. HuffmanTree(const vector & v) { list< tfc > l; // Store each vector entry in a tree. for (vector::const_iterator pos = v.begin(); pos != v.end(); ++pos) l.push_back(tfc(*pos, tfc(), tfc())); theTree = build(l); return; } // Obtain the Huffman's tree. const tfc& getTree(void) { return theTree; } // Read a Huffman encoding tree from the istream. // The returned tree should be ignored if the istream is in a bad state. // The frequencies in the returned tree are to be ignored. friend istream& operator>>(istream& in, HuffmanTree & t) { t = HuffmanTree(HuffmanTree::readTree(in)); return in; } // Write a Huffman encoding tree to the ostream. friend ostream& operator<<(ostream& out, HuffmanTree & t) { return printTree(out, t.getTree()); } // Return true iff the tree is a leaf. static bool leafp(const tfc & t) { return !t.empty() && t.left().empty() && t.right().empty(); } private: tfc theTree; // Convert a tfc to a HuffmanTree. HuffmanTree(tfc t) : theTree(t) {} // Compare two frequency-character pairs using the frequencies. static bool compare(const tfc & tfc1, const tfc & tfc2) { return tfc1.item().first < tfc2.item().first; } // Build the Huffman tree (really the tfc). // input <- a doubly-linked list of trees // output-> a tfc static tfc build(list< tfc > & l) { assert(l.size() != 0); if (l.size() == 1) // only one tree so this is the answer return l.front(); else { // Merge the two trees with the least frequencies. list< tfc >::iterator m = min_element(l.begin(), l.end(), compare); assert(m != l.end()); tfc mTree = *m; l.erase(m); list< tfc >::iterator n = min_element(l.begin(), l.end(), compare); assert(n != l.end()); tfc nTree = *n; l.erase(n); l.push_back(tfc(freqChar(mTree.item().first + nTree.item().first, 'i' /* ignored */), mTree, nTree)); return build(l); } } // Read the tree. static tfc readTree(istream& in) { char c1, c2; if (in.get(c1) && in.get(c2)) { if (c1 == 'i') { tfc l = readTree(in); tfc r = readTree(in); return tfc(freqChar(1,'a' /* ignored */), l, r); } else { assert(c1 == 'l'); return tfc(freqChar(1,c2), tfc(), tfc()); } } else return tfc(); // bad input } // Print the tree in prefix notation. static ostream& printTree(ostream& out, const tfc & t) { if (leafp(t)) return out.put('l').put(t.item().second); else { // internal node out.put('i').put('i'); printTree(out,t.left()); printTree(out,t.right()); return out; } } }; #endif // HUFFMAN_TREE_H