Advertisement
xxeell

Huffman

Mar 24th, 2020
197
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 10.71 KB | None | 0 0
  1. using System;
  2. using System.Text;
  3. using System.Collections.Generic;
  4. using System.IO;
  5. using System.Linq;
  6. using System.Diagnostics;
  7.  
  8. namespace ForDZ
  9. {
  10.     class HuffmanTree<T> where T : IComparable<T>
  11.     {
  12.         #region INNER_CLASSES
  13.         public enum NodeType
  14.         {
  15.             Void = 0,
  16.             Value = 1
  17.         }
  18.  
  19.         public interface INode
  20.         {
  21.             NodeType Type { get; }
  22.             INode Left { get; set; }
  23.             INode Right { get; set; }
  24.             int Height { get; }
  25.         }
  26.  
  27.         public class Node : INode
  28.         {
  29.             public T Value { get; set; }
  30.             public INode Left { get; set; }
  31.             public INode Right { get; set; }
  32.             public NodeType Type { get => NodeType.Value; }
  33.             public int Height { get; set; }
  34.         }
  35.  
  36.         public class VoidNode : INode
  37.         {
  38.             public INode Left { get; set; }
  39.             public INode Right { get; set; }
  40.             public NodeType Type { get => NodeType.Void; }
  41.             public int Height { get; set; }
  42.         }
  43.  
  44.         private struct NodeWithCount : IComparable<NodeWithCount>
  45.         {
  46.             public INode Node;
  47.             public int Count;
  48.  
  49.             public int CompareTo(NodeWithCount other)
  50.             {
  51.                 int count_cmp = Count.CompareTo(other.Count);
  52.  
  53.                 if(count_cmp != 0)
  54.                 {
  55.                     return count_cmp;
  56.                 }
  57.  
  58.                 return Node.Height.CompareTo(other.Node.Height);
  59.             }
  60.         }
  61.         #endregion
  62.  
  63.         private INode root;
  64.         public Dictionary<T, int> ElementsCounts { get; private set; }
  65.         public Dictionary<T, bool[]> Table { get; private set; }
  66.  
  67.         public HuffmanTree(Dictionary<T, int> elements_counts)
  68.         {
  69.             ElementsCounts = new Dictionary<T, int>(elements_counts.Count);
  70.             foreach(var t in elements_counts.OrderBy(x => x.Value))
  71.             {
  72.                 ElementsCounts.Add(t.Key, t.Value);
  73.             }
  74.                
  75.             InitTree();
  76.             Table = new Dictionary<T, bool[]>();
  77.             AddLeavesToTable(root, (new bool[0]));
  78.         }
  79.  
  80.         public HuffmanTree(T[] input) : this(CountsOfElements(input))
  81.         {
  82.             //
  83.         }
  84.  
  85.         private static Dictionary<T, int> CountsOfElements(T[] input)
  86.         {
  87.             Dictionary<T, int> res = new Dictionary<T, int>();
  88.  
  89.             foreach (T element in input)
  90.             {
  91.                 if (res.ContainsKey(element))
  92.                 {
  93.                     res[element]++;
  94.                 }
  95.                 else
  96.                 {
  97.                     res.Add(element, 1);
  98.                 }
  99.             }
  100.  
  101.             return res;
  102.         }
  103.  
  104.         private void InitTree()
  105.         {
  106.             List<NodeWithCount> nodes = new List<NodeWithCount>(ElementsCounts.Count);
  107.             nodes.AddRange(ElementsCounts
  108.                 .Select(x =>
  109.                 new NodeWithCount
  110.                 {
  111.                     Node = new Node
  112.                     {
  113.                         Value = x.Key,
  114.                         Left = null,
  115.                         Right = null,
  116.                         Height = 0
  117.                     },
  118.                     Count = x.Value
  119.                 }));
  120.             nodes = nodes.OrderBy(x => x).ToList();
  121.  
  122.             while (nodes.Count > 1)
  123.             {
  124.                 NodeWithCount tuple = new NodeWithCount
  125.                 {
  126.                     Node = new VoidNode
  127.                     {
  128.                         Left = nodes[0].Node,
  129.                         Right = nodes[1].Node,
  130.                         Height =
  131.                             (nodes[0].Node.Height < nodes[1].Node.Height ?
  132.                                 nodes[0].Node.Height :
  133.                                 nodes[1].Node.Height) + 1
  134.                     },
  135.                     Count = nodes[0].Count + nodes[1].Count
  136.                 };
  137.                 nodes.RemoveAt(0);
  138.                 nodes[0] = tuple;
  139.  
  140.                 nodes = nodes.OrderBy(x => x).ToList();
  141.             }
  142.  
  143.             root = nodes[0].Node;
  144.         }
  145.  
  146.         private void AddLeavesToTable(INode node, IEnumerable<bool> code)
  147.         {
  148.             if (node.Type == NodeType.Value)
  149.             {
  150.                 Table.Add((node as Node).Value, code.ToArray());
  151.                 return;
  152.             }
  153.  
  154.             AddLeavesToTable(node.Left, code.Append(false).ToArray());
  155.             AddLeavesToTable(node.Right, code.Append(true).ToArray());
  156.         }
  157.     }
  158.  
  159.     static class HuffmanCoder<T> where T : IComparable<T>
  160.     {
  161.         public static bool[] Code(HuffmanTree<T> Tree, T[] input)
  162.         {
  163.             foreach (var t in Tree.ElementsCounts)
  164.             {
  165.                 Console.Write($"{t.Key} -> {t.Value} -> ");
  166.                 foreach (var i in Tree.Table[t.Key])
  167.                 {
  168.                     Console.Write(i ? 1 : 0);
  169.                 }
  170.                 Console.Write($" ({Tree.Table[t.Key].Length})");
  171.                 Console.WriteLine();
  172.             }
  173.  
  174.             List<bool> res = new List<bool>();
  175.  
  176.             foreach (T elem in input)
  177.             {
  178.                 res.AddRange(Tree.Table[elem]);
  179.             }
  180.  
  181.             return res.ToArray();
  182.         }
  183.     }
  184.  
  185.     static class HuffmanDecoder<T> where T : IComparable<T>
  186.     {
  187.         private static bool CheckEqual(bool[] a, bool[] b)
  188.         {
  189.             if (a.Length != b.Length)
  190.             {
  191.                 return false;
  192.             }
  193.  
  194.             for (int i = 0, len = a.Length; i < len; i++)
  195.             {
  196.                 if (a[i] != b[i])
  197.                 {
  198.                     return false;
  199.                 }
  200.             }
  201.  
  202.             return true;
  203.         }
  204.  
  205.         public static T[] Decode(HuffmanTree<T> Tree, IEnumerable<bool> coded_sequence)
  206.         {
  207.             Dictionary<bool[], T> BackTable = new Dictionary<bool[], T>();
  208.             foreach (T elem in Tree.Table.Keys)
  209.             {
  210.                 BackTable.Add(Tree.Table[elem], elem);
  211.             }
  212.  
  213.             List<T> res = new List<T>();
  214.  
  215.             List<bool> current_code = new List<bool>();
  216.             bool[][] keys = BackTable.Keys.ToArray();
  217.  
  218.             foreach (bool t in coded_sequence)
  219.             {
  220.                 current_code.Add(t);
  221.  
  222.                 for (int i = 0; i < keys.Length; i++)
  223.                 {
  224.                     if (CheckEqual(keys[i], current_code.ToArray()))
  225.                     {
  226.                         res.Add(BackTable[keys[i]]);
  227.                         current_code.Clear();
  228.                         break;
  229.                     }
  230.                 }
  231.             }
  232.  
  233.             return res.ToArray();
  234.         }
  235.     }
  236.  
  237.     static class FileHuffmanTree
  238.     {
  239.         public static void CodeToFileWithHuffman(string content, string file_name)
  240.         {
  241.             char[] input = content.ToArray();
  242.  
  243.             HuffmanTree<char> tree = new HuffmanTree<char>(input);
  244.  
  245.             bool[] coded_sequence = HuffmanCoder<char>.Code(tree, input);
  246.  
  247.             List<byte> bytes = new List<byte>();
  248.  
  249.             bytes.AddRange(BitConverter.GetBytes(tree.ElementsCounts.Count));
  250.             foreach (var t in tree.ElementsCounts)
  251.             {
  252.                 bytes.AddRange(BitConverter.GetBytes(t.Key));
  253.                 bytes.AddRange(BitConverter.GetBytes(t.Value));
  254.             }
  255.  
  256.             int byte_length = coded_sequence.Length;
  257.             bytes.AddRange(BitConverter.GetBytes(byte_length));
  258.             byte t_byte = 0;
  259.             for (int i = 0; i < coded_sequence.Length; i++)
  260.             {
  261.                 int bit_index = i % 8;
  262.  
  263.                 if (coded_sequence[i])
  264.                 {
  265.                     byte adder = (byte)(1 << bit_index);
  266.                     t_byte = (byte)(t_byte | adder);
  267.                 }
  268.  
  269.                 if (bit_index == 7)
  270.                 {
  271.                     bytes.Add(t_byte);
  272.                     t_byte = 0;
  273.                 }
  274.             }
  275.             bytes.Add(t_byte);
  276.  
  277.             File.WriteAllBytes(file_name, bytes.ToArray());
  278.         }
  279.  
  280.         public static char[] DecodeToFileWithHuffman(string file_name)
  281.         {
  282.             byte[] file_bytes = File.ReadAllBytes(file_name);
  283.             MemoryStream stream = new MemoryStream(file_bytes);
  284.  
  285.             byte[] buffer = new byte[4];
  286.             stream.Read(buffer, 0, 4);
  287.             int table_count = BitConverter.ToInt32(buffer, 0);
  288.             Dictionary<char, int> char_table = new Dictionary<char, int>();
  289.             for (int i = 0; i < table_count; i++)
  290.             {
  291.                 stream.Read(buffer, 0, 2);
  292.                 char letter = BitConverter.ToChar(buffer, 0);
  293.                 stream.Read(buffer, 0, 4);
  294.                 int count = BitConverter.ToInt32(buffer, 0);
  295.                 char_table.Add(letter, count);
  296.             }
  297.  
  298.             stream.Read(buffer, 0, 4);
  299.             int bit_buffer_len = BitConverter.ToInt32(buffer, 0);
  300.             List<bool> coded_sequence = new List<bool>();
  301.  
  302.             while (stream.Read(buffer, 0, 1) > 0)
  303.             {
  304.                 byte t = buffer[0];
  305.                 for (int i = 0; i < 8; i++)
  306.                 {
  307.                     coded_sequence.Add((t & (1 << i)) != 0);
  308.                 }
  309.             }
  310.  
  311.             coded_sequence = coded_sequence.Take(bit_buffer_len).ToList();
  312.  
  313.             HuffmanTree<char> tree = new HuffmanTree<char>(char_table);
  314.  
  315.             return HuffmanDecoder<char>.Decode(tree, coded_sequence);
  316.         }
  317.     }
  318.  
  319.     class Program
  320.     {
  321.         static void Main(string[] args)
  322.         {
  323.             Stopwatch stopwatch = new Stopwatch();
  324.  
  325.             string input = File.ReadAllText("input.txt");
  326.  
  327.             stopwatch.Start();
  328.             FileHuffmanTree.CodeToFileWithHuffman(input, "coded_input.dla");
  329.             stopwatch.Stop();
  330.  
  331.             Console.Write($"Coding complete ");
  332.             Console.Write($"from {stopwatch.ElapsedMilliseconds} ms ");
  333.             Console.WriteLine($"({stopwatch.ElapsedMilliseconds / 1000.0} s)");
  334.  
  335.             stopwatch.Reset();
  336.  
  337.             stopwatch.Start();
  338.             char[] file = FileHuffmanTree.DecodeToFileWithHuffman("coded_input.dla");
  339.             stopwatch.Stop();
  340.  
  341.             StringBuilder char_list = new StringBuilder();
  342.             char_list.Append(file);
  343.             File.WriteAllText("decoded_input.txt", char_list.ToString());
  344.  
  345.             Console.Write($"DeCoding complete ");
  346.             Console.Write($"from {stopwatch.ElapsedMilliseconds} ms ");
  347.             Console.WriteLine($"({stopwatch.ElapsedMilliseconds / 1000.0} s)");
  348.  
  349.             Console.WriteLine("\n\nend.");
  350.             Console.ReadKey();
  351.         }
  352.     }
  353. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement