/// <summary> /// Decodes a given binary path to represent it's string value /// </summary> /// <param name="bits">BitArray for traversing the tree</param> /// <returns></returns> public string Decode(BitArray bits) { HuffmanNode current = Root; string decodedString = string.Empty; foreach (bool bit in bits) { //Find the correct current node depending on the bit set or not set. current = (bit ? current.Right ?? current : current.Left ?? current); if (current.IsLeaf()) { decodedString += current.Character; current = Root; } } return(decodedString); }
/// <summary> /// Builds the Huffman tree /// </summary> public void BuildTree() { if (!Frequencies.FrequencyTable.Any()) { throw new ArgumentNullException("Frequency table is empty"); } _nodes.Clear(); //As we build a new tree, first make sure it's clean :) foreach (KeyValuePair <char, int> symbol in Frequencies.FrequencyTable) { _nodes.Add(new HuffmanNode() { Character = symbol.Key, Frequency = symbol.Value }); } while (_nodes.Count > 1) { List <HuffmanNode> orderedNodes = _nodes.OrderBy(node => node.Frequency).ToList(); if (orderedNodes.Count >= 2) { List <HuffmanNode> takenNodes = orderedNodes.Take(2).ToList(); HuffmanNode parent = new HuffmanNode() { Character = null, Frequency = takenNodes[0].Frequency + takenNodes[1].Frequency, Left = takenNodes[0], Right = takenNodes[1] }; //Remove the childnodes from the original node list and add the new parent node _nodes.Remove(takenNodes[0]); _nodes.Remove(takenNodes[1]); _nodes.Add(parent); } } Root = _nodes.FirstOrDefault(); }
/// <summary> /// Determines whether a given Huffman node is a leaf or not. /// A node is considered to be a leaf when it has no childnodes /// </summary> /// <param name="node">A huffman node</param> /// <returns>True if no children are left, false otherwise</returns> public static bool IsLeaf(this HuffmanNode node) { return (null == node.Left && null == node.Right); }