Main Page   Packages   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members   Search  

C:/temp/src/j2k/DataType/Huffman/HuffMan.hpp

Go to the documentation of this file.
00001 /***************************************************************************
00002  *** Huffman coding tree example program.                                ***
00003  ***************************************************************************
00004 
00005 First, read from the data file a set of strings and associated frequencies.
00006 
00007 These are placed onto a list of (single node) Huffman trees.
00008 
00009 Next, build a single Huffman coding tree for the set.
00010 
00011 The strings and their codes are then output,
00012 with CodeTable storing the coding for each input string.
00013 
00014 Next, read commands to "encode" or "decode" strings,
00015 providing the appropriate output.
00016 ***************************************************************************/
00017 
00018 #include <j2k/Fred/Standard.hpp>
00019 #include <ctype.h>
00020 
00021 #include <j2k/DataType/HuffMan/LettFreq.hpp>
00022 typedef LettFreq* Belem;
00023 
00024 #include <j2k/DataType/BinTree.hpp>
00025 #include <j2k/DataType/HuffMan/HuffTree.hpp>
00026 
00027 typedef HuffTree* Elem;
00028 
00029 // Use for freelist link class.
00030 #include <j2k/DataType/Link/SLink.hpp>
00031 #include <j2k/DataType/Link/SList.hpp>
00032 
00033 // Load the member functions
00034 #include <j2k/DataType/Link/SLink.cpp>
00035 #include <j2k/DataType/Link/SList.cpp>
00036 
00037 #define CODELEN 20 // Max length of a huffman code
00038 
00039 // Print out the elements of list "in"
00040 void print(List& in) 
00041 {
00042   if (in.isEmpty()) 
00043   {
00044     cout << "()\n";
00045   }
00046   else 
00047   {
00048     in.setFirst();
00049     cout << "( " << in.currValue();
00050     in.next();
00051 
00052     while (in.isInList()) 
00053     {
00054       cout << ", " << in.currValue();
00055       in.next();
00056     }
00057 
00058     cout << " )\n";
00059   }
00060 }
00061 
00062 double total = 0;
00063 
00064 // overload for the << operator to allow "nice" output of a LettFreq object
00065 ostream& operator << (ostream& s, LettFreq* z)
00066 {
00067   cout << "In lettfreq << operator\n";
00068   if (z->letter() != '\0')
00069   {
00070     return(s << z->letter() << "/" << z->weight());
00071   }
00072   else
00073   {
00074     return(s << "NULL/" << z->weight());
00075   }
00076 }
00077 
00078 // overload for the << operator to allow "nice" output of HuffTree object
00079 ostream& operator << (ostream& s, HuffTree* z)
00080 { 
00081   return(s << z->root()->value());
00082 }
00083 
00084 // CodeTable stores the codewords and their associated codes.
00085 struct CodeTableEntry 
00086 {
00087   LettFreq* entrydata;
00088   char code[CODELEN];
00089 
00090 } CodeTable[100];
00091 
00092 int CodeCount = 0; // Number of entries in CodeTable
00093 FILE *fp;
00094 
00095 List templist; // Holds the Huffman forest during construction
00096 
00097 // Read a list of strings and frequencies from standard input,
00098 // building a list of Huffman coding tree nodes
00099 void read_freqs(List& hufflist)
00100 { 
00101   char buff[100];
00102   char buff2[100];
00103   char *ptr;
00104   char *ptr2;
00105   int  freq;
00106   HuffTree* temptree;
00107 
00108   while (TRUE)
00109   {
00110     if (!fgets(buff, 99, fp))  // read the next entry
00111     { 
00112       cout << "No more codes to read -- where is end?\n";
00113       assert(FALSE); 
00114     }
00115 
00116     // process the entry, creating a new HuffTree
00117     for(ptr=buff; *ptr==' '; ptr++);
00118     {
00119       if (!strncmp(ptr, "end", 3))
00120       { 
00121         cout<< "Print out the tree:\n";
00122         print(hufflist);
00123         return;
00124       }
00125     }
00126 
00127     if (*ptr != '"')
00128     {
00129       cout << "First char was not a quote mark.\n";
00130       assert(FALSE);
00131     }
00132 
00133     for (ptr2=buff2,ptr++; *ptr!='"'; ptr++)
00134     {
00135       *ptr2++ = *ptr;
00136     }
00137 
00138     *ptr2 = '\0'; // End of string
00139 
00140     for (ptr++; *ptr==' '; ptr++);
00141 
00142     if (!isdigit(*ptr)) assert(FALSE);
00143 
00144     freq = atoi(ptr);
00145 
00146     CodeTable[CodeCount].entrydata = new LettFreq(freq, buff2[0]);
00147 
00148     temptree = new HuffTree(CodeTable[CodeCount++].entrydata);
00149 
00150     // put in the list in sorted order
00151     // WARNING: This may be considered buggy.  Nodes with equal weight will
00152     // be put in reverse order of appearance, not in alphabetical order.
00153     for (hufflist.setFirst(); hufflist.isInList(); hufflist.next())
00154     {
00155       if (temptree->weight() <= hufflist.currValue()->weight())
00156       {
00157          hufflist.insert(temptree);
00158          break;
00159       }
00160     }
00161 
00162     if (!hufflist.isInList())
00163     {
00164         hufflist.append(temptree);
00165     }
00166 
00167   } // End of while loop
00168 }
00169 
00170 #include <j2k/DataType/HuffMan/HuffBld.hpp>
00171 
00172 // Find the index in CodeTable for the codeword
00173 int getindex(char codeword) 
00174 {
00175   register int i;
00176 
00177   for ( i = 0; i < CodeCount; i++ ) 
00178   {
00179     if ( codeword == CodeTable[i].entrydata->letter() ) 
00180     {
00181       return i;
00182     }
00183   }
00184 
00185   return -1; // Not found
00186 }
00187 
00188 
00189 // Print out the codes, and also insert these codes into CodeTable
00190 void output_tree( BinNode* node, char* prefix, int level ) 
00191 {
00192   int index;
00193   assert( node != NULL ); // This is a Full Binary Tree so should NOT happen
00194   if ( node->isLeaf() ) 
00195   {
00196     cout << node->value()->letter() << "\t" << prefix << "\n";
00197     index = getindex( node->value()->letter() );
00198     strcpy( CodeTable[index].code, prefix );
00199     total += level * node->value()->weight();
00200   } 
00201   else 
00202   {
00203     prefix[ level     ] = '0';
00204     prefix[ level + 1 ] = '\0';
00205     output_tree( node->leftchild(),  prefix, level+1 );
00206 
00207     prefix[ level     ] = '1';
00208     prefix[ level + 1 ] = '\0';
00209     output_tree( node->rightchild(), prefix, level+1 );
00210 
00211     prefix[ level     ] = '\0';
00212   }
00213 }
00214 
00215 
00216 void do_commands( HuffTree* tree ) 
00217 {
00218   BinNode* temp;
00219   char*    currchar;
00220   char     buff[80];
00221   int      index;
00222 
00223   while( fgets(buff, 99, fp) ) 
00224   {
00225     if( !strncmp(buff, "decode", 6) ) 
00226     {
00227       for( currchar = buff; *currchar != '"'; currchar++ );
00228 
00229       cout << "Decode " << currchar++;
00230       temp = tree->root();
00231 
00232       while (*currchar != '"')  // Traverse the tree
00233       {
00234         if ( *currchar == '0' ) 
00235         {
00236           temp = temp->leftchild();
00237         } 
00238         else if ( *currchar == '1' ) 
00239         {
00240           temp = temp->rightchild();
00241         } 
00242         else 
00243         {
00244           cout << "Bad input! " << *currchar << "\n";
00245           abort();
00246         }
00247 
00248         if ( temp->isLeaf() ) 
00249         {
00250           cout << temp->value()->letter();
00251           temp = tree->root();   // reset at root
00252         }
00253 
00254         currchar++;
00255 
00256       } // End of 2nd while()
00257 
00258     } 
00259     else if( !strncmp(buff, "encode", 6) ) 
00260     {
00261 
00262       for ( currchar = buff; *currchar != '"'; currchar++);
00263 
00264       cout << "Encode " << currchar++;
00265 
00266       // Assume codes are characters.  Should generalize this.
00267       while( *currchar != '"' )   
00268       {
00269         if (*currchar == ' ') 
00270         {
00271           cout << ' ';
00272         } 
00273         else 
00274         {
00275           index = getindex( *currchar );
00276           assert( index < CodeCount );    // Must find it
00277           cout << CodeTable[index].code;
00278         }
00279 
00280         currchar++;  // This is what needs generalized
00281       }
00282     }
00283     cout << "\n";
00284 
00285   } // End of 1st while()
00286 }
00287 
00288 
00289 int main( int argc, char** argv ) 
00290 {
00291   HuffTree* codes;
00292   char prefix[30];
00293 
00294   if (argc == 1) 
00295   {
00296     fp = stdin;
00297   } 
00298   else 
00299   {
00300     fp = fopen(argv[1], "rt");
00301     cout << "Read frequencies\n";
00302     read_freqs(templist);
00303     cout << "Build the tree\n";
00304     codes = build_tree(templist);
00305     cout << "Output the tree\n";
00306     output_tree(codes->root(), prefix, 0);
00307     cout << "Average code length is ";
00308     cout << total/(double)codes->weight() << "\n";
00309     do_commands(codes);
00310     return(FALSE);
00311   }
00312 }

Generated on Sun Oct 14 18:46:17 2001 for Standard J2K Library by doxygen1.2.11.1 written by Dimitri van Heesch, © 1997-2001