private static List<bool> Traverse(Node node, char symbol, List<bool> data) { if (node.Left == null && node.Right == null) { return symbol == node.Symbol ? data : null; } if (node.Left != null) { var path = new List<bool>(); path.AddRange(data); path.Add(false); var left = Traverse(node.Left, symbol, path); if (left != null) { return left; } } if (node.Right != null) { var path = new List<bool>(); path.AddRange(data); path.Add(true); var right = Traverse(node.Right, symbol, path); if (right != null) { return right; } } return null; }
public void Build(string text) { if (text == null) { throw new ArgumentNullException("text"); } this._Root = null; var frequencies = new Dictionary<char, int>(); this._Codes.Clear(); foreach (var t in text) { int frequency; if (frequencies.TryGetValue(t, out frequency) == false) { frequency = 0; } frequencies[t] = frequency + 1; } var nodes = frequencies.Select( symbol => new Node() { Symbol = symbol.Key, Frequency = symbol.Value, }).ToList(); while (nodes.Count > 1) { var orderedNodes = nodes .OrderBy(n => n.Frequency).ToList(); if (orderedNodes.Count >= 2) { var taken = orderedNodes.Take(2).ToArray(); var first = taken[0]; var second = taken[1]; var parent = new Node() { Symbol = '\0', Frequency = first.Frequency + second.Frequency, Left = first, Right = second, }; nodes.Remove(first); nodes.Remove(second); nodes.Add(parent); } this._Root = nodes.FirstOrDefault(); } foreach (var frequency in frequencies) { var bits = Traverse(this._Root, frequency.Key, new List<bool>()); if (bits == null) { throw new InvalidOperationException(string.Format( "could not traverse '{0}'", frequency.Key)); } this._Codes.Add(frequency.Key, new BitArray(bits.ToArray())); } this.TotalBits = GetTotalBits(this._Root); }
private static int GetTotalBits(Node root) { var queue = new Queue<Node>(); queue.Enqueue(root); int totalBits = 0; while (queue.Count > 0) { var node = queue.Dequeue(); if (node.Left == null && node.Right == null) { continue; } totalBits += node.Frequency; if (node.Left != null && node.Left.Left != null && node.Left.Right != null) { queue.Enqueue(node.Left); } if (node.Right != null && node.Right.Left != null && node.Right.Right != null) { queue.Enqueue(node.Right); } } return totalBits; }