public class HuffmanTree { private List nodes = new List(); public Node Root { get; set; } public Dictionary Frequencies = new Dictionary(); public void Build(string source) { for (int i = 0; i < source.Length; i++) { if (!Frequencies.ContainsKey(source[i])) { Frequencies.Add(source[i], 0); } Frequencies[source[i]]++; } foreach (KeyValuePair symbol in Frequencies) { nodes.Add(new Node() { Symbol = symbol.Key, Frequency = symbol.Value }); } while (nodes.Count > 1) { List orderedNodes = nodes.OrderBy(node => node.Frequency).ToList(); if (orderedNodes.Count >= 2) { // Take first two items List taken = orderedNodes.Take(2).ToList(); // Create a parent node by combining the frequencies Node parent = new Node() { Symbol = '*', Frequency = taken[0].Frequency + taken[1].Frequency, Left = taken[0], Right = taken[1] }; nodes.Remove(taken[0]); nodes.Remove(taken[1]); nodes.Add(parent); } this.Root = nodes.FirstOrDefault(); } } public BitArray Encode(string source) { List encodedSource = new List(); for (int i = 0; i < source.Length; i++) { List encodedSymbol = this.Root.Traverse(source[i], new List()); encodedSource.AddRange(encodedSymbol); } BitArray bits = new BitArray(encodedSource.ToArray()); return bits; } public string Decode(BitArray bits) { Node current = this.Root; string decoded = ""; foreach(bool bit in bits){ if (bit) { if (current.Right != null) { current = current.Right; } } else { if(current.Left != null) { current = current.Left; } } if (IsLeaf(current)) { decoded += current.Symbol; current = this.Root; } } return decoded; } public bool IsLeaf(Node node) { return (node.Left == null && node.Right == null); } } public class Node { public char Symbol { get; set; } public int Frequency { get; set; } public Node Right { get; set; } public Node Left { get; set; } public List Traverse(char symbol,List data) { // Leaf if (Right == null && Left == null) { if (symbol.Equals(this.Symbol)) { return data; } else { return null; } } else { List left = null; List right = null; if (Left != null) { List leftPath = new List(); leftPath.AddRange(data); leftPath.Add(false); left = Left.Traverse(symbol, leftPath); } if (Right != null) { List rightPath = new List(); rightPath.AddRange(data); rightPath.Add(true); right = Right.Traverse(symbol, rightPath); } if (left != null) { return left; } else { return right; } } } } class Program { static void Main() { HuffmanTree huffmanTree = new HuffmanTree(); string input; using (StreamReader fileIn = new StreamReader(@"C:\Users\lexpr\Documents\Visual Studio 2015\Projects\ConsoleApplication1\input.txt")) { input = fileIn.ReadToEnd(); } huffmanTree.Build(input); BitArray encoded = huffmanTree.Encode(input); string decoded = huffmanTree.Decode(encoded); Console.WriteLine("Decoded: " + decoded); Console.Write("Encoded: "); using (StreamWriter file = new StreamWriter(@"C:\Users\lexpr\Documents\Visual Studio 2015\Projects\ConsoleApplication1\output.txt")) { foreach (bool bit in encoded) { file.Write((bit? 1 : 0) + ""); Console.Write((bit ? 1 : 0) + ""); } Console.WriteLine(); } } }