public static HashTable<char, BitStream> MakeEncodingTable(Node node, BitStream progress) { HashTable<char,BitStream> result = new HashTable<char,BitStream>(char.MaxValue,HashChar); //if the current node is not null and it is a leaf, we want to add it to result if (node != null && node.Left == null && node.Right == null) { //we only store leaf nodes in the result array //make a new bit stream BitStream stream = new BitStream(); //append progress to it stream.Append(progress); //add node.data and the new stream to result result.Add(node.Data, stream); } //else if the node is not null, we are going to want to process it's childern else { if (node != null && node.Left != null) { //if left subtree is not null //make new bit stream BitStream stream = new BitStream(); //append progress stream.Append(progress); //append 0 (because we are going left) stream.Append(false); //recursivley call this function on node.Left with the new stream we just created //store the result of the previous call in a local hashtable HashTable<char, BitStream> local = MakeEncodingTable(node.Left, stream); //loop through the just created hash table(the return of the recursive function) SLinkedList<char> list = local.Keys; for (int i = 0; i < list.Size; i++) { //add each key value pair to this function's result hash table result.Add(list[i], local[list[i]]); //we do this because the results of each recursion bubble back up to the top. //by the time the root returns, all of the leaf nodes will be in the final hash table }//end loop }//end if if (node != null && node.Right != null) { //repeat above for the right subtree BitStream stream = new BitStream(); stream.Append(progress); stream.Append(true); HashTable<char, BitStream> local = MakeEncodingTable(node.Right, stream); SLinkedList<char> list = local.Keys; for (int i = 0; i < list.Size; i++) { result.Add(list[i], local[list[i]]); } }//end else } return result; }
public void Append(BitStream stream) { // Cache stream size as a member variable. We do this because int streamSize = stream.BitCount; // it's valid to add elements mid loop. If we do this however, // we will face an infinite loop if the stream passed in is the // same stream we are writing to. To avoid this scenario, we need // a 'Stream Size' to be recorded in a variable local to this function // we loop on this integer, not stream.Size. //(Inside the loop) Get every bit, and call the existing Append function for (int i = 0; i < streamSize; i++) { if (stream.BitAt(i)) { Append(true); } else{ Append(false); } } }
public static byte[] Compress(string toCompress) { //then at the end of the function we're going to convert it to an array, and return it. Vector<byte> result = new Vector<byte>(); //make an encoding table out of the huffman tree, out of a frequency table Console.WriteLine("Making Huffman frequency table"); HashTable<char, int> FreqTable = MakeFrequencyTable(toCompress); //copy to memory because we access it multiple times Console.WriteLine("Making Huffman tree"); Node huffmanTree = MakeHuffmanTree(FreqTable); Console.WriteLine("Making Huffman encoding table"); HashTable<char, BitStream> encodingTable = MakeEncodingTable(huffmanTree, new BitStream()); // add to memory because accessed twice //convert the size of the frequency table to bytes. Console.WriteLine("Converting to bytes"); byte[] freqToByte = IntToBytes(FreqTable.Size); //and all four bytes to the resuld linked list Console.WriteLine("Adding bytes bytes"); result.AddRange(freqToByte); //next loop through the frequency table SLinkedList<char> list = FreqTable.Keys; Console.WriteLine("looping through frequency table"); for (int i = 0; i < list.Size; i++) { //convert current key to two bytes byte[] key = CharToBytes(list[i]); //add both bytes to the linked list result.AddRange(key); //convert the current value to foure bytes, byte[] value = IntToBytes(FreqTable[list[i]]); //add alll four bytes to the linked list result.AddRange(value); }//end loop //make new bitstream (datastream) to hold bits BitStream datastream = new BitStream(); //loop through the string Console.WriteLine("Looping through input and adding to datastream"); for (int i = 0; i < toCompress.Length; i++) { //append the bitstream of the encoding table to the newely created bitstream datastream.Append(encodingTable[toCompress[i]]); }//end loop //get the bit streams bit count as an integer int streamBitCount = datastream.BitCount; //convert this integer to bytes and add it to the result list Console.WriteLine("Converting bytes"); byte[] streambitByte = IntToBytes(streamBitCount); result.AddRange(streambitByte); Console.WriteLine("Copying Bytes"); result.AddRange(datastream.Bytes); //finally convert the result list to a byte array. Console.WriteLine("Convert results list to byte array"); byte[] byteResult = result.ToArray(); //return the array return byteResult; }
public static void Main(string[] args) { BitStream stream = new BitStream (); stream.Append (true); stream.Append (true); stream.Append (true); string debug = stream.ToString (); Console.WriteLine (debug); if (debug != "111") { Error ("Expecting 111, got " + debug); Console.ReadLine(); return; } stream.Append (false); stream.Append (true); stream.Append (false); stream.Append (false); stream.Append (true); debug = stream.ToString (); Console.WriteLine (debug); if (debug != "11101001") { Error ("Expecting 11101001, got " + debug); Console.ReadLine(); return; } Console.WriteLine ("0: " + stream.BitAt (0) + " / True"); if (!stream.BitAt (0)) { Error ("Expecting bit 0 to be on, it was not"); Console.ReadLine(); return; } Console.WriteLine ("1: " + stream.BitAt (1) + " / True"); if (!stream.BitAt (1)) { Error ("Expecting bit 1 to be on, it was not"); Console.ReadLine(); return; } Console.WriteLine ("2: " + stream.BitAt (2) + " / True"); if (!stream.BitAt (2)) { Error ("Expecting bit 2 to be on, it was not"); Console.ReadLine(); return; } Console.WriteLine ("3: " + stream.BitAt (3) + " / False"); if (stream.BitAt (3)) { Error ("Expecting bit 3 to be off, it was not"); Console.ReadLine(); return; } Console.WriteLine ("4: " + stream.BitAt (4) + " / True"); if (!stream.BitAt (4)) { Error ("Expecting bit 4 to be on, it was not"); Console.ReadLine(); return; } Console.WriteLine ("5: " + stream.BitAt (5) + " / False"); if (stream.BitAt (5)) { Error ("Expecting bit 5 to be off, it was not"); Console.ReadLine(); return; } Console.WriteLine ("6: " + stream.BitAt (6) + " / False"); if (stream.BitAt (6)) { Error ("Expecting bit 6 to be off, it was not"); Console.ReadLine(); return; } Console.WriteLine ("7: " + stream.BitAt (7) + " / True"); if (!stream.BitAt (7)) { Error ("Expecting bit 7 to be on, it was not"); Console.ReadLine(); return; } stream.Append (stream); debug = stream.ToString (); Console.WriteLine (debug); if (debug != "1110100111101001") { Error ("Expecting 1110100111101001, got " + debug); Console.ReadLine(); return; } stream.Append ("110011"); debug = stream.ToString (); Console.WriteLine (debug); if (debug != "1110100111101001110011") { Error ("Expecting 1110100111101001110011, got " + debug); Console.ReadLine(); return; } try { stream.Append("1A"); Error("ERROR! Should not be able to insert A"); Console.ReadLine(); return; } catch (System.Exception e) { Console.WriteLine ("Was not able to insert A (As expected)"); } debug = stream.ToString (); Console.WriteLine (debug); if (debug != "11101001111010011100111") { Error ("Expecting 11101001111010011100111, got " + debug); Console.ReadLine(); return; } Console.WriteLine(stream.ByteAt (0) + " / 233"); if (stream.ByteAt (0) != 233) { Error ("Expected byte at 0 to be 233, not: " + stream.ByteAt (0)); Console.ReadLine(); return; } Console.WriteLine (stream.ByteAt (1) + " / 233"); if (stream.ByteAt (1) != 233) { Error ("Expected byte at 1 to be 233, not: " + stream.ByteAt (1)); Console.ReadLine(); return; } Console.WriteLine (stream.ByteAt (2) + " / 206"); if (stream.ByteAt (2) != 206) { Error ("Expected byte at 2 to be 206, not: " + stream.ByteAt (2)); Console.ReadLine(); return; } Console.WriteLine ("Num bytes: " + stream.ByteCount + " / 3"); if (stream.ByteCount != 3) { Error ("Expecting ByteCount to be 3, not: " + stream.ByteCount); Console.ReadLine(); return; } Console.WriteLine ("Num bits: " + stream.BitCount + " / 23"); if (stream.BitCount != 23) { Error ("Expecting BitCount to be 23, not: " + stream.BitCount); Console.ReadLine(); return; } Console.WriteLine (stream.ToString ()); byte[] bits = stream.Bytes; for (int i = 0; i < bits.Length; ++i) { Console.Write(Convert.ToString(bits[i], 2).PadLeft(8, '0')); } Console.Write ("\n"); Console.ReadLine(); }