/// <summary> /// Builds a Huffman tree based on symbols quantity dictionary. /// </summary> /// <param name="valueComparer"> /// Comparer used as a last resort to define /// relation between two huffman tree nodes. It is used to define the /// relation only if other means based on Quantity and Subtree depth fail. /// It should never return 0 (equality) for different elements. /// </param> /// <param name="symbolQuantityDic">dicrionary containing quantity /// of symbol occurences for this tree to build.</param> /// <returns>Huffman tree.</returns> public IHuffmanTreeNode <T> BuildTree(IComparer <T> valueComparer, Dictionary <T, int> symbolQuantityDic) { var nodeComparer = new HuffmanTreeNodeComparer <T>(valueComparer); if (symbolQuantityDic.Keys.Count == 0) { throw new Exception("This builder requires at least one symbol in quantity dictionary."); } if (symbolQuantityDic.Keys.Count == 1) { var only = symbolQuantityDic.Keys.First(); return(new HuffmanTreeNode <T>( value: only, quantity: 1)); } var priorityQueue = GetHuffmanNodePriorityQueue(nodeComparer, symbolQuantityDic); while (priorityQueue.Count() > 1) { var first = priorityQueue.DeleteMin(); var second = priorityQueue.DeleteMin(); var mergedNode = Merge(first, second); priorityQueue.Add(mergedNode); } return(priorityQueue.DeleteMin()); }
/// <summary> /// </summary> /// <returns>An initial priority queue created for building Huffman tree.</returns> private IntervalHeap <HuffmanTreeNode <T> > GetHuffmanNodePriorityQueue( HuffmanTreeNodeComparer <T> nodeComparer, Dictionary <T, int> symbolQuantityDic) { var priorityQueue = new IntervalHeap <HuffmanTreeNode <T> >(nodeComparer); priorityQueue.AddAll(symbolQuantityDic.Select( s => new HuffmanTreeNode <T>( value: s.Key, quantity: s.Value ) )); return(priorityQueue); }