Построение дерева "Код Хаффмана" - C#

Узнай цену своей работы

Формулировка задачи:

Доброго времени суток, есть коллекция символов с числом их повторений, как реализовать этот шаг:
Выбираются два свободных узла дерева с наименьшими весами. Создается их родитель с весом, равным их суммарному весу. <- Этот интересует
Если я правильно понимаю, коллекция состоит, например: h - 1, e - 1, o - 1, l - 2. Берутся первые два символа объединяются и в итоге получается след.: he - 2, o - 1, l - 2, и так до тех пор пока не останется одна ячейка: helo - 5. Дальше встает вопрос,что каждому символу необходима присвоить значение 1 или 0,когда это делать?
Кто-нибудь подскажет?

Решение задачи: «Построение дерева "Код Хаффмана"»

textual
Листинг программы
 public class HuffmanTree
    {
        private List<Node> nodes = new List<Node>();
        public Node Root { get; set; }
        public Dictionary<char, int> Frequencies = new Dictionary<char, int>();
 
        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<char, int> symbol in Frequencies)
            {
                nodes.Add(new Node() { Symbol = symbol.Key, Frequency = symbol.Value });
            }
 
            while (nodes.Count > 1)
            {
                List<Node> orderedNodes = nodes.OrderBy(node => node.Frequency).ToList<Node>();
 
                if (orderedNodes.Count >= 2)
                {
                    // Take first two items
                    List<Node> taken = orderedNodes.Take(2).ToList<Node>();
 
                    // 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<bool> encodedSource = new List<bool>();
 
            for (int i = 0; i < source.Length; i++)
            {
                List<bool> encodedSymbol = this.Root.Traverse(source[i], new List<bool>());
                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<bool> Traverse(char symbol,List<bool> data)
        {
            // Leaf
            if (Right == null && Left == null)
            {
                if (symbol.Equals(this.Symbol))
                {
                    return data;
                }
                else
                {
                    return null;
                }
            }
            else
            {
                List<bool> left = null;
                List<bool> right = null;
 
                if (Left != null)
                {
                    List<bool> leftPath = new List<bool>();
                    leftPath.AddRange(data);
                    leftPath.Add(false);
 
                    left = Left.Traverse(symbol, leftPath);
                }
 
                if (Right != null)
                {
                    List<bool> rightPath = new List<bool>();
                    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(@""))
            {
                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(@""))
                {
                foreach (bool bit in encoded)
                     {
                        file.Write((bit? 1 : 0) + "");
                        Console.Write((bit ? 1 : 0) + "");
                      }
                     Console.WriteLine();
 
                 }
        }
    }

ИИ поможет Вам:


  • решить любую задачу по программированию
  • объяснить код
  • расставить комментарии в коде
  • и т.д
Попробуйте бесплатно

Оцени полезность:

9   голосов , оценка 3.667 из 5