示例#1
0
        static void Main(string[] args)
        {
            string text =
                "This is short sample text to encode.";
            var    tree    = new HuffTree();
            string encoded = tree.Encode(text);

            tree.Reset();
            string decoded = tree.Decode(encoded);

            Console.WriteLine(decoded);
        }
示例#2
0
        public byte[] Compression(char[] textToEncrypt, string originalName)
        {
            //Calculamos la tabla:
            List <NodeTable> table = GenerateTable(textToEncrypt);
            //Incicializamos una cola e insertamos los valores:
            HuffQueue <NodeTable> queue = new HuffQueue <NodeTable>();

            AddToQueue(table, queue);
            //Agregamos al árbol de Huffman:
            HuffTree tree = new HuffTree();

            tree.Insert(queue, tree);
            //Agregar al árbol, las codificaciones:
            tree.AddBinary(tree.rootOriginal, 0, "");
            //Añadimos a la tabla las codificaciones de cada caracter en su lugar correspondiente:
            //Para eso debemos llenar una lista con los caracteres y codificaciones del árbol:
            List <NodeTable> auxiliar = new List <NodeTable>();

            tree.BinarysIncludes(tree.rootOriginal, auxiliar);
            //Ya con la lista, se lo agregamos a la "table":
            for (int i = 0; i < auxiliar.Count; i++)
            {
                for (int j = 0; j < table.Count; j++)
                {
                    if (auxiliar[i].character == table[j].character)
                    {
                        table[j].binary = auxiliar[i].binary;
                    }
                }
            }
            //Escribimos la codificación en lugar del texto original:
            string        result     = "";
            StringBuilder concatenar = new StringBuilder();

            for (int i = 0; i < textToEncrypt.Length; i++)
            {
                for (int j = 0; j < table.Count; j++)
                {
                    if (textToEncrypt[i].ToString() == table[j].character)
                    {
                        //result += table[j].binary;
                        concatenar.Append(table[j].binary);
                    }
                }
            }
            result = concatenar.ToString();
            //Separaramos por 8 bits y si no completa, agregar ceros:
            List <string> bytes = SeparateBytes(result);
            //Convertimos los bytes a decimales y los agregamos a otra lista:
            List <int> decimals = new List <int>();

            for (int i = 0; i < bytes.Count; i++)
            {
                decimals.Add(ConvertBinaryToDecimal(bytes[i]));
            }
            //
            //
            //
            List <byte> oName = BytesToOriginalName(originalName);

            //
            //
            //
            //Mandamos a escribir todo el texto (incluyendo su metadata):
            byte[] response = ReturnBytesToWrite(table, decimals, oName);
            return(response);
        }
示例#3
0
        public List <char> Decompression(List <byte> bytes)
        {
            int startOfCompressedText = 0;
            //La primera posición del arreglo nos dirá cuántos carateres diferentes tiene:
            int diferentsCharacters = bytes[0];
            //La segunda posición del arreglo nos dirá cuántos bytes ocupan las frecuencias:
            int bytesOfFrequencies = bytes[1];
            //Se valida cuántos son:
            List <NodeTable> table = new List <NodeTable>();

            //Si solo ocupan 1 byte, entonces...
            if (bytesOfFrequencies == 1)
            {
                int numberToReadMetadata = (diferentsCharacters * 2) + 1;
                startOfCompressedText = numberToReadMetadata;
                for (int i = 2; i <= numberToReadMetadata; i++)
                {
                    //Leemos primero los caracteres:
                    char character = (char)bytes[i];
                    i++;
                    int frequency = bytes[i];
                    //Agregamos a la "table":
                    NodeTable aux = new NodeTable
                    {
                        character = character.ToString(),
                        frequency = frequency
                    };
                    table.Add(aux);
                }
            }
            //Si ocupan 2 bytes, entonces...
            else if (bytesOfFrequencies == 2)
            {
                int numberToReadMetadata = (diferentsCharacters * 3) + 1;
                startOfCompressedText = numberToReadMetadata;
                for (int i = 2; i < numberToReadMetadata; i++)
                {
                    //Leemos primero los caracteres:
                    char character = (char)bytes[i];
                    i++;
                    //Ya que las frecuencias ocupan dos bytes, debemos:
                    //Primero: Convertir la 2da. y 3ra. posición a bytes
                    int frequency1 = bytes[i];
                    i++;
                    int frequency2 = bytes[i];
                    //Segundo: Ya convertidos a bytes, ambos se deben convertir a binarios
                    string binary1 = ConvertDecimalToBinary(frequency1);
                    if (binary1 == "")
                    {
                        binary1 = "0";
                    }
                    string binary2 = ConvertDecimalToBinary(frequency2);
                    if (binary2.Length < 8)
                    {
                        string copy = binary2;
                        binary2 = "";
                        int restant = 8 - copy.Length;
                        for (int j = 0; j < restant; j++)
                        {
                            binary2 += "0";
                        }
                        binary2 += copy;
                    }
                    //Tercero: Concatenamos los dos binarios, para formar uno solo
                    string resultantBinary = binary1 + binary2;
                    //Cuarto: Convertimos el binario en decimal para obtener la frecuencia total
                    int frequencyTotal = ConvertBinaryToDecimal(resultantBinary);
                    //Agregamos a la "table":
                    NodeTable aux = new NodeTable
                    {
                        character = character.ToString(),
                        frequency = frequencyTotal
                    };
                    table.Add(aux);
                }
            }
            //Se llena la tablita con sus probabilidades y se vuelve a hacer todo el proceso de la cola y el árbol, etc...
            //Se calcula la probabilidad de cada caracter:
            double totalFrequency = 0;

            for (int i = 0; i < table.Count; i++)
            {
                totalFrequency += table[i].frequency;
            }
            for (int i = 0; i < table.Count; i++)
            {
                table[i].probability = table[i].frequency / totalFrequency;
            }
            //Incicializamos una cola e insertamos los valores:
            HuffQueue <NodeTable> queue = new HuffQueue <NodeTable>();

            AddToQueue(table, queue);
            //Agregamos al árbol de Huffman:
            HuffTree tree = new HuffTree();

            tree.Insert(queue, tree);
            //Agregar al árbol, las codificaciones:
            tree.AddBinary(tree.rootOriginal, 0, "");
            //Añadimos a la tabla las codificaciones de cada caracter en su lugar correspondiente:
            //Para eso debemos llenar una lista con los caracteres y codificaciones del árbol:
            List <NodeTable> auxiliar = new List <NodeTable>();

            tree.BinarysIncludes(tree.rootOriginal, auxiliar);
            //Ya con la lista, se lo agregamos a la "table":
            for (int i = 0; i < auxiliar.Count; i++)
            {
                for (int j = 0; j < table.Count; j++)
                {
                    if (auxiliar[i].character == table[j].character)
                    {
                        table[j].binary = auxiliar[i].binary;
                    }
                }
            }
            //Ya con toda la table hecha, procedemos a leer el texto compreso para su descompresión:
            string        largeBinary = "";
            StringBuilder aux2        = new StringBuilder();

            for (int i = startOfCompressedText + 1; i < bytes.Count; i++)
            {
                //Se convierte cada decimal a binario y se agrega a un solo string con el binario largo original:
                string binaryIndividual = ConvertDecimalToBinary(bytes[i]);
                //Si el tamaño, es menor a 8, entonces se agregan 0´s al inicio:
                if (binaryIndividual.Length < 8)
                {
                    int    restants = 8 - binaryIndividual.Length;
                    string others   = "";
                    for (int j = 0; j < restants; j++)
                    {
                        others += "0";
                    }
                    string ok = others + binaryIndividual;
                    aux2.Append(ok);
                }
                else
                {
                    aux2.Append(binaryIndividual);
                }
            }
            largeBinary = aux2.ToString();
            StringBuilder aux4 = new StringBuilder();

            aux4.Append(largeBinary);
            //Ya con la cadena larga de binario... se van haciendo comparaciones en la "table" para obtener el texto original:
            bool        empty     = false;
            List <char> respuesta = new List <char>();

            while (!empty)
            {
                bool match    = false;
                int  counter  = 0;
                int  posMatch = 0;
                while (!match)
                {
                    counter++;
                    for (int i = 0; i < table.Count; i++)
                    {
                        if (aux4.ToString(0, counter) == table[i].binary)
                        {
                            char[] aux = table[i].character.ToCharArray();
                            respuesta.Add(aux[0]);
                            posMatch = counter;
                            match    = true;
                        }
                    }
                }
                //Se elimina lo que ya se encontró:
                if (match)
                {
                    aux4.Remove(0, posMatch);
                }
                //Se comprueba si ya se debe dejar de leer:
                if (respuesta.Count == totalFrequency)
                {
                    empty = true;
                }
            }
            return(respuesta);
        }
示例#4
0
        public void Insert(HuffQueue <NodeTable> valuesToInsert, HuffTree _root)
        {
            List <NodeHuffTree> listAux = new List <NodeHuffTree>();

            //Validar si aún hay parejar para sacar en la cola:
            while (valuesToInsert.Nodes >= 2)
            {
                //Si está vacío el árbol se realiza el primer proceso de inserción:
                if (rootOriginal == null)
                {
                    //Se sacan los dos nodos de la cola y se guardan:
                    object first = valuesToInsert.ReturnRoot();
                    valuesToInsert.DeleteRoot(valuesToInsert);
                    NodeTable firstSon = (NodeTable)first;
                    object    second   = valuesToInsert.ReturnRoot();
                    valuesToInsert.DeleteRoot(valuesToInsert);
                    NodeTable secondSon = (NodeTable)second;
                    //Se crean los primeros dos nodos hermanos del HuffTree
                    NodeHuffTree firstNewSon = new NodeHuffTree
                    {
                        character   = firstSon.character,
                        probability = firstSon.probability,
                    };
                    NodeHuffTree secondNewSon = new NodeHuffTree
                    {
                        character   = secondSon.character,
                        probability = secondSon.probability,
                    };
                    //Se crea la raíz por primera vez:
                    NodeHuffTree root = new NodeHuffTree
                    {
                        character   = "N" + proxNode.ToString(),
                        probability = firstNewSon.probability + secondNewSon.probability,
                    };
                    //Se valida quién será el hijo izquierdo y quién el hijo derecho
                    if (secondNewSon.probability > firstNewSon.probability)
                    {
                        root.nodeRight = secondNewSon;
                        root.nodeLeft  = firstNewSon;
                    }
                    else
                    {
                        root.nodeRight = firstNewSon;
                        root.nodeLeft  = secondNewSon;
                    }
                    //Se agrega el padre a los dos hermanos:
                    firstNewSon.nodeFather  = root;
                    secondNewSon.nodeFather = root;
                    //Se asigna la raíz:
                    rootOriginal = root;
                    //Se agrega el padre creado a la cola:
                    NodeTable toInsertAgainOnQueue = new NodeTable
                    {
                        character   = "N" + proxNode.ToString(),
                        probability = root.probability
                    };
                    proxNode++;
                    valuesToInsert.Insert(toInsertAgainOnQueue, root.probability);
                }
                //Si el árbol ya tiene algo, se realiza el siguiente proceso:
                else
                {
                    //Se sacan los dos nodos de la cola y se guardan:
                    object first = valuesToInsert.ReturnRoot();
                    valuesToInsert.DeleteRoot(valuesToInsert);
                    NodeTable firstSon = (NodeTable)first;
                    object    second   = valuesToInsert.ReturnRoot();
                    valuesToInsert.DeleteRoot(valuesToInsert);
                    NodeTable secondSon = (NodeTable)second;
                    //Se crean los dos nodos hermanos del HuffTree:
                    NodeHuffTree firstNewSon = new NodeHuffTree
                    {
                        character   = firstSon.character,
                        probability = firstSon.probability,
                    };
                    NodeHuffTree secondNewSon = new NodeHuffTree
                    {
                        character   = secondSon.character,
                        probability = secondSon.probability,
                    };
                    //Se crea la nueva raíz que será padre de los dos nodos hermanos sin importar cuál sea el caso:
                    NodeHuffTree root = new NodeHuffTree
                    {
                        character   = "N" + proxNode.ToString(),
                        probability = firstNewSon.probability + secondNewSon.probability,
                    };
                    //Ya que tenemos los hermanos, se valida si alguno de los dos ya está en la Raiz del HuffTree:
                    //Si hay alguno, entonces se busca en la listAux si el otro que no era igual a la raíz está:
                    if ((rootOriginal.character == firstNewSon.character) || (rootOriginal.character == secondNewSon.character))
                    {
                        bool matchOnList = false;
                        int  posMatch    = 0;
                        //Se busca en la listAux:
                        for (int i = 0; i < listAux.Count; i++)
                        {
                            if ((listAux[i].character == firstNewSon.character) || (listAux[i].character == secondNewSon.character))
                            {
                                matchOnList = true;
                                posMatch    = i;
                            }
                        }
                        //Si se encontró, entonces se saca... se hace hermano con el que ya está en la raíz del HuffTree:
                        if (matchOnList)
                        {
                            //Se obtiene el nodo de la lista y se elimina:
                            NodeHuffTree valueMatchOnList = listAux[posMatch];
                            listAux.RemoveAt(posMatch);
                            //Se hace una copia de la rootOriginal;
                            HuffTree auxilarClone = (HuffTree)_root.Clone();
                            //Ya que tenemos los dos valores, solo insertamos de la manera correcta:
                            if (valueMatchOnList.probability > auxilarClone.rootOriginal.probability)
                            {
                                root.nodeLeft  = auxilarClone.rootOriginal;
                                root.nodeRight = valueMatchOnList;
                            }
                            else
                            {
                                root.nodeLeft  = valueMatchOnList;
                                root.nodeRight = auxilarClone.rootOriginal;
                            }
                            //Se agrega el padre a los dos hermanos:
                            valueMatchOnList.nodeFather          = root;
                            auxilarClone.rootOriginal.nodeFather = root;
                            //Se cambia la raíz
                            rootOriginal = root;
                            //Se agrega el padre creado a la cola:
                            NodeTable toInsertAgainOnQueue = new NodeTable
                            {
                                character   = "N" + proxNode.ToString(),
                                probability = root.probability
                            };
                            proxNode++;
                            valuesToInsert.Insert(toInsertAgainOnQueue, root.probability);
                        }
                        //Si no se encontró el otro en la lista... entonces solo se hace hermano con la raíz (el que no es igual):
                        else
                        {
                            //Se hace una copia de la rootOriginal;
                            HuffTree auxilarClone = (HuffTree)_root.Clone();
                            //Si es igual al firstNewSon, entonces la raíz se volverá hermano con el secondNewSon
                            if (auxilarClone.rootOriginal.character == firstNewSon.character)
                            {
                                if (secondNewSon.probability > auxilarClone.rootOriginal.probability)
                                {
                                    root.nodeLeft  = auxilarClone.rootOriginal;
                                    root.nodeRight = secondNewSon;
                                }
                                else
                                {
                                    root.nodeLeft  = secondNewSon;
                                    root.nodeRight = auxilarClone.rootOriginal;
                                }
                                auxilarClone.rootOriginal.nodeFather = root;
                                secondNewSon.nodeFather = root;
                            }
                            //Si es igual al secondNewSon, entonces la raíz se volverá hermano con el firstNewSon
                            else if (auxilarClone.rootOriginal.character == secondNewSon.character)
                            {
                                if (firstNewSon.probability > auxilarClone.rootOriginal.probability)
                                {
                                    root.nodeLeft  = auxilarClone.rootOriginal;
                                    root.nodeRight = firstNewSon;
                                }
                                else
                                {
                                    root.nodeLeft  = firstNewSon;
                                    root.nodeRight = auxilarClone.rootOriginal;
                                }
                                auxilarClone.rootOriginal.nodeFather = root;
                                firstNewSon.nodeFather = root;
                            }
                            //Se cambia la raíz
                            rootOriginal = root;
                            //Se agrega el padre creado a la cola:
                            NodeTable toInsertAgainOnQueue = new NodeTable
                            {
                                character   = "N" + proxNode.ToString(),
                                probability = root.probability
                            };
                            proxNode++;
                            valuesToInsert.Insert(toInsertAgainOnQueue, root.probability);
                        }
                    }
                    //Si no hay alguno, entonces:
                    else
                    {
                        //Se busca en la listAux para encontrar alguno de los 2:
                        bool matchOnList = false;
                        for (int i = 0; i < listAux.Count; i++)
                        {
                            if ((listAux[i].character == firstNewSon.character) || (listAux[i].character == secondNewSon.character))
                            {
                                matchOnList = true;
                            }
                        }
                        //Si no se encuentra, entonces solo se inserta el root en la lista:
                        if (!matchOnList)
                        {
                            if (secondNewSon.probability > firstNewSon.probability)
                            {
                                root.nodeLeft  = firstNewSon;
                                root.nodeRight = secondNewSon;
                            }
                            else
                            {
                                root.nodeLeft  = secondNewSon;
                                root.nodeRight = firstNewSon;
                            }
                            //Se agrega el padre a los dos hermanos:
                            firstNewSon.nodeFather  = root;
                            secondNewSon.nodeFather = root;
                            //Se agrega el padre creado a la cola:
                            NodeTable toInsertAgainOnQueue = new NodeTable
                            {
                                character   = "N" + proxNode.ToString(),
                                probability = root.probability
                            };
                            proxNode++;
                            valuesToInsert.Insert(toInsertAgainOnQueue, root.probability);
                            //Se inserta en la listAux
                            listAux.Add(root);
                        }
                        //Si se encuentra, entonces se busca si los 2 están en la lista o si solo 1 está:
                        else
                        {
                            //Se busca denuevo en la lista, pero esta vez, ambos por separado:
                            bool matchFirstNewSon    = false;
                            int  posMatchFirstNewSon = 0;
                            for (int i = 0; i < listAux.Count; i++)
                            {
                                if (listAux[i].character == firstNewSon.character)
                                {
                                    matchFirstNewSon    = true;
                                    posMatchFirstNewSon = i;
                                }
                            }
                            bool matchSecondNewSon    = false;
                            int  posMatchSecondNewSon = 0;
                            for (int i = 0; i < listAux.Count; i++)
                            {
                                if (listAux[i].character == secondNewSon.character)
                                {
                                    matchSecondNewSon    = true;
                                    posMatchSecondNewSon = i;
                                }
                            }
                            //Si encuentra a los dos en la lista:
                            if (matchFirstNewSon && matchSecondNewSon)
                            {
                                //Se guardan y se remueven de la lista:
                                NodeHuffTree valueMatchOnList1 = listAux[posMatchFirstNewSon];
                                NodeHuffTree valueMatchOnList2 = listAux[posMatchSecondNewSon];
                                listAux.RemoveAt(posMatchFirstNewSon);
                                //Se valida si no es mayor la posición, ya que se habrá eliminado:
                                if (posMatchSecondNewSon > posMatchFirstNewSon)
                                {
                                    posMatchSecondNewSon -= 1;
                                }
                                listAux.RemoveAt(posMatchSecondNewSon);
                                //Se valida en qué posición van (izquierda, derecha):
                                if (valueMatchOnList2.probability > valueMatchOnList1.probability)
                                {
                                    root.nodeLeft  = valueMatchOnList1;
                                    root.nodeRight = valueMatchOnList2;
                                }
                                else
                                {
                                    root.nodeLeft  = valueMatchOnList2;
                                    root.nodeRight = valueMatchOnList1;
                                }
                                //Se agrega el padre a los dos hermanos:
                                valueMatchOnList1.nodeFather = root;
                                valueMatchOnList2.nodeFather = root;
                                //Se agrega el padre creado a la cola:
                                NodeTable toInsertAgainOnQueue = new NodeTable
                                {
                                    character   = "N" + proxNode.ToString(),
                                    probability = root.probability
                                };
                                proxNode++;
                                valuesToInsert.Insert(toInsertAgainOnQueue, root.probability);
                                //Se inserta en la listAux
                                listAux.Add(root);
                            }
                            //Si solo se encuentra uno en la lista:
                            else if (matchFirstNewSon || matchSecondNewSon)
                            {
                                //Si solo se encuentra el matchFirstNewSon
                                if (matchFirstNewSon)
                                {
                                    //Se guardan y se remueven de la lista:
                                    NodeHuffTree valueMatchOnList1 = listAux[posMatchFirstNewSon];
                                    listAux.RemoveAt(posMatchFirstNewSon);
                                    //Se valida en qué posición van (izquierda, derecha):
                                    if (secondNewSon.probability > valueMatchOnList1.probability)
                                    {
                                        root.nodeLeft  = valueMatchOnList1;
                                        root.nodeRight = secondNewSon;
                                    }
                                    else
                                    {
                                        root.nodeLeft  = secondNewSon;
                                        root.nodeRight = valueMatchOnList1;
                                    }
                                    //Se agrega el padre a los dos hermanos:
                                    valueMatchOnList1.nodeFather = root;
                                    secondNewSon.nodeFather      = root;
                                    //Se agrega el padre creado a la cola:
                                    NodeTable toInsertAgainOnQueue = new NodeTable
                                    {
                                        character   = "N" + proxNode.ToString(),
                                        probability = root.probability
                                    };
                                    proxNode++;
                                    valuesToInsert.Insert(toInsertAgainOnQueue, root.probability);
                                    //Se inserta en la listAux
                                    listAux.Add(root);
                                }
                                //Si solo se encuentra el matchSecondNewSon
                                else if (matchSecondNewSon)
                                {
                                    //Se guardan y se remueven de la lista:
                                    NodeHuffTree valueMatchOnList2 = listAux[posMatchSecondNewSon];
                                    listAux.RemoveAt(posMatchSecondNewSon);
                                    //Se valida en qué posición van (izquierda, derecha):
                                    if (firstNewSon.probability > valueMatchOnList2.probability)
                                    {
                                        root.nodeLeft  = valueMatchOnList2;
                                        root.nodeRight = firstNewSon;
                                    }
                                    else
                                    {
                                        root.nodeLeft  = firstNewSon;
                                        root.nodeRight = valueMatchOnList2;
                                    }
                                    //Se agrega el padre a los dos hermanos:
                                    valueMatchOnList2.nodeFather = root;
                                    firstNewSon.nodeFather       = root;
                                    //Se agrega el padre creado a la cola:
                                    NodeTable toInsertAgainOnQueue = new NodeTable
                                    {
                                        character   = "N" + proxNode.ToString(),
                                        probability = root.probability
                                    };
                                    proxNode++;
                                    valuesToInsert.Insert(toInsertAgainOnQueue, root.probability);
                                    //Se inserta en la listAux
                                    listAux.Add(root);
                                }
                            }
                        }
                    }
                }
            }
        }