public void CreateModel()
 {
     Number              = 3;
     Weight              = 2;
     Left                = new DynamicHuffmanTree();
     Left.SpecialSymbol  = "Esc";
     Left.Number         = 1;
     Left.Weight         = 1;
     Right               = new DynamicHuffmanTree();
     Right.SpecialSymbol = "EoF";
     Right.Number        = 2;
     Right.Weight        = 1;
 }
        private DynamicHuffmanTree FindParent(DynamicHuffmanTree Child)
        {
            if (Left == Child || Right == Child || this == Child)
            {
                return(this);
            }
            DynamicHuffmanTree Result = null;

            if (Right != null)
            {
                Result = Right.FindParent(Child);
            }
            if (Result == null && Left != null)
            {
                Result = Left.FindParent(Child);
            }
            return(Result);
        }
        private DynamicHuffmanTree Find(int NumberToFind)
        {
            if (Number == NumberToFind)
            {
                return(this);
            }
            DynamicHuffmanTree Result = null;

            if (Right != null)
            {
                Result = Right.Find(NumberToFind);
            }
            if (Result == null && Left != null)
            {
                Result = Left.Find(NumberToFind);
            }
            return(Result);
        }
        private DynamicHuffmanTree Find(string SpecialSymbolToFind)
        {
            if (SpecialSymbol == SpecialSymbolToFind)
            {
                return(this);
            }
            DynamicHuffmanTree Result = null;

            if (Right != null)
            {
                Result = Right.Find(SpecialSymbolToFind);
            }
            if (Result == null && Left != null)
            {
                Result = Left.Find(SpecialSymbolToFind);
            }
            return(Result);
        }
        public string Encode(Byte?SymbolToEncode)
        {
            string             Code = "";
            char               a    = Convert.ToChar(SymbolToEncode);
            DynamicHuffmanTree KeyLeave;

            if (SymbolToEncode == null)
            {
                KeyLeave = Find("EoF");
            }
            else
            {
                KeyLeave = Find(SymbolToEncode);
                if (KeyLeave == null)
                {
                    Code     = DynamicHuffmanTree.ToBinaryString(SymbolToEncode);
                    KeyLeave = Find("Esc");
                }
            }
            DynamicHuffmanTree Parent = this.FindParent(KeyLeave);

            do
            {
                if (Parent.Left == KeyLeave)
                {
                    Code = "0" + Code;
                }
                if (Parent.Right == KeyLeave)
                {
                    Code = "1" + Code;
                }
                KeyLeave = Parent;
                Parent   = this.FindParent(KeyLeave);
            }while (Parent != KeyLeave);

            Rebuild(SymbolToEncode);

            return(Code);
        }
        private void Rebuild(Byte?SymbolToEncode)
        {
            DynamicHuffmanTree CurrentVertex = Find(SymbolToEncode);

            if (CurrentVertex == null)
            {
                DynamicHuffmanTree NewVertex        = new DynamicHuffmanTree();
                DynamicHuffmanTree LastVertex       = Find(1);
                DynamicHuffmanTree LastVertexParent = FindParent(LastVertex);
                DynamicHuffmanTree VertexWithSymbol = new DynamicHuffmanTree();
                VertexWithSymbol.Symbol = SymbolToEncode;
                VertexWithSymbol.Weight = 1;
                NewVertex.Weight        = LastVertex.Weight + VertexWithSymbol.Weight;
                LastVertexParent.Left   = NewVertex;
                NewVertex.Left          = VertexWithSymbol;
                NewVertex.Right         = LastVertex;
                CurrentVertex           = NewVertex;
                ReNumber();
            }
            else
            {
                CurrentVertex.Weight++;
            }

            while (CurrentVertex != this)
            {
                int Number = CurrentVertex.Number;
                while (CurrentVertex.Weight == Find(Number + 1).Weight + 1)
                {
                    Number++;
                }

                if (Number != CurrentVertex.Number)
                {
                    DynamicHuffmanTree VertexForChange;
                    VertexForChange = Find(Number);

                    if (FindParent(VertexForChange) != FindParent(CurrentVertex))
                    {
                        DynamicHuffmanTree Parent1 = FindParent(VertexForChange);
                        DynamicHuffmanTree Parent2 = FindParent(CurrentVertex);
                        if (Parent1.Left == VertexForChange)
                        {
                            Parent1.Left = CurrentVertex;
                        }
                        if (Parent1.Right == VertexForChange)
                        {
                            Parent1.Right = CurrentVertex;
                        }
                        if (Parent2.Left == CurrentVertex)
                        {
                            Parent2.Left = VertexForChange;
                        }
                        if (Parent2.Right == CurrentVertex)
                        {
                            Parent2.Right = VertexForChange;
                        }
                    }
                    else
                    {
                        DynamicHuffmanTree Parent = FindParent(VertexForChange);
                        if (Parent.Left == VertexForChange)
                        {
                            Parent.Left  = CurrentVertex;
                            Parent.Right = VertexForChange;
                        }
                        if (Parent.Left == CurrentVertex)
                        {
                            Parent.Left  = VertexForChange;
                            Parent.Right = CurrentVertex;
                        }
                    }
                }
                CurrentVertex = FindParent(CurrentVertex);
                CurrentVertex.Weight++;
                ReNumber();
            }
        }
        public static double Encode(string file_name)
        {
            bool         opened      = false;
            BinaryWriter output_file = null;

            try
            {
                _source_file = new BinaryReader(File.OpenRead(file_name));
                output_file  = new BinaryWriter(File.Create($@"{System.Windows.Forms.Application.StartupPath}\output.dynhuf"));
                opened       = true;
            }
            catch (Exception e)
            {
                System.Windows.Forms.MessageBox.Show(e.Message);
            }

            if (opened)
            {
                DynamicHuffmanTree encoding_model = new DynamicHuffmanTree();
                encoding_model.CreateModel();

                bool   end_of_file = false;
                Byte   symbol      = 0;
                string code        = "";
                string buffer      = "";

                char[]   CharTypeBuffer;
                FileInfo file_info = new FileInfo(file_name);
                CharTypeBuffer = (file_info.Extension.Substring(1, file_info.Extension.Length - 1) + ".").ToCharArray();
                output_file.Write(CharTypeBuffer);

                while (!end_of_file)
                {
                    try
                    {
                        symbol = _source_file.ReadByte();
                    }
                    catch
                    {
                        end_of_file = true;
                    }

                    if (!end_of_file)
                    {
                        code = encoding_model.Encode(symbol);
                    }
                    else
                    {
                        code = encoding_model.Encode(null);
                    }

                    code   = buffer + code;
                    buffer = code.Substring(code.Length - (code.Length % 8), (code.Length) - (code.Length - (code.Length % 8)));
                    code   = code.Remove(code.Length - (code.Length % 8), (code.Length) - (code.Length - (code.Length % 8)));

                    while (code != "")
                    {
                        output_file.Write(DynamicHuffmanTree.ToByte(code.Substring(0, 8)));
                        code = code.Remove(0, 8);
                    }

                    if (end_of_file)
                    {
                        while (buffer.Length != 8)
                        {
                            buffer += "0";
                        }
                        output_file.Write(DynamicHuffmanTree.ToByte(buffer));
                    }
                }

                _source_file.Close();
                output_file.Close();

                BinaryReader ResultFile = new BinaryReader(File.OpenRead($@"{System.Windows.Forms.Application.StartupPath}\output.dynhuf"));
                BinaryReader BaseFile   = new BinaryReader(File.OpenRead(file_name));

                double result = (double)ResultFile.BaseStream.Length / (double)BaseFile.BaseStream.Length;

                ResultFile.Close();
                BaseFile.Close();
                return(result);
            }

            return(-1);
        }