Ejemplo n.º 1
0
        /// <summary>
        /// Converts a <see cref="Dictionary{TKey, TValue}"/>, which maps <see cref="BitPath"/> instances to their assigned symbols, into a <see cref="HuffmanNode{T}"/>.
        /// </summary>
        /// <param name="paths">Mapping of bit paths to the symbols. All possible paths must terminate in a symbol.</param>
        /// <exception cref="ArgumentException">Thrown when the <paramref name="paths"/> dictionary is missing a possible path, or a path is unreachable.</exception>
        public static HuffmanNode <T> FromSymbolPaths(Dictionary <BitPath, T> paths)
        {
            int longestBranch = paths.Select(path => (int)path.Key.Length).DefaultIfEmpty(0).Max();
            int totalLeaves   = 0;

            HuffmanNode <T> GenerateNodeBranch(in BitPath prefix, bool nextBit)
            {
                BitPath branch = prefix.Add(nextBit);

                if (paths.TryGetValue(branch, out T symbol))
                {
                    ++totalLeaves;
                    return(new HuffmanNode <T> .Leaf(symbol));
                }
                else if (branch.Length >= longestBranch)
                {
                    return(new HuffmanNode <T> .Dummy()); // TODO hack to "support" Huffman trees with missing branches
                }
                else
                {
                    return(GenerateNode(branch));
                }
            }

            HuffmanNode <T> GenerateNode(in BitPath stream)
            {
                return(new HuffmanNode <T> .Path(GenerateNodeBranch(stream, false), GenerateNodeBranch(stream, true)));
            }

            HuffmanNode <T> root = GenerateNode(new BitPath());

            if (totalLeaves != paths.Count)
            {
                throw new ArgumentException("Impossible symbol paths, " + (paths.Count - totalLeaves) + " symbol(s) could not be reached.", nameof(paths));
            }

            return(root);
        }
Ejemplo n.º 2
0
 protected override IEnumerable <KeyValuePair <T, BitPath> > ListValues(BitPath prefix)
 {
     yield return(new KeyValuePair <T, BitPath>(value, prefix));
 }
Ejemplo n.º 3
0
 /// <summary>
 /// Recursively searches through all child nodes, and returns all values mapped to their respective bit sequences.
 /// </summary>
 /// <param name="prefix">Sequence of bits used to get to the current node. Every level of recursion on <see cref="Path"/> nodes appends a 0/1 bit, <see cref="Leaf"/> nodes return the final value.</param>
 protected abstract IEnumerable <KeyValuePair <T, BitPath> > ListValues(BitPath prefix);