예제 #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);
        }
예제 #2
0
 public Path(HuffmanNode <T> left, HuffmanNode <T> right)
 {
     this.left  = left;
     this.right = right;
 }
 public void Deconstruct(out HuffmanNode <T> node, out int frequency)
 {
     node      = Node;
     frequency = Frequency;
 }
 public Freq(HuffmanNode <T> node, int frequency)
 {
     this.Node      = node;
     this.Frequency = frequency;
 }