void PopulateSymbolTable(int[] frequencies) { Symbols = new HuffmanTableEntry[NumSymbols]; for (int i = 0; i < NumSymbols; i++) { Symbols[i] = new HuffmanTableEntry { Symbol = i, Count = frequencies[i] }; } }
// TODO: This completely fails if there is only 1 observed symbol. We should fix this. // However, in practice there should always be at least one literal symbol + EOF symbol (shouldn't be compressing 0 byte files). public void ConstructTree() { var symbolsToProcess = new List <HuffmanTableEntry>(Symbols.Where(s => s.Count > 0)); while (symbolsToProcess.Count > 1) { // Pop the lowest count symbols off the list, and insert a tree node each time you loop. // Loop until you only have one symbol, the top of the tree. var lowest1 = symbolsToProcess[0]; var lowest2 = symbolsToProcess[1]; if (lowest1.Count > lowest2.Count) { lowest1 = symbolsToProcess[1]; lowest2 = symbolsToProcess[0]; } for (int i = 2; i < symbolsToProcess.Count; i++) { if (symbolsToProcess[i].Count < lowest1.Count) { lowest2 = lowest1; lowest1 = symbolsToProcess[i]; } else if (symbolsToProcess[i].Count < lowest2.Count) { lowest2 = symbolsToProcess[i]; } } // Now, lowest1 and lowest2 should point to the lowest two probability items in the list. // So, create a merged node with lowest two probability items. var merged = new HuffmanTableEntry { Symbol = -1, Count = lowest1.Count + lowest2.Count }; lowest1.Parent = merged; lowest2.Parent = merged; // Insert merged node and pop off lowest symbolsToProcess.Remove(lowest1); symbolsToProcess.Remove(lowest2); symbolsToProcess.Add(merged); } }