public HuffmanTree(FrequencyDictionary frequencyDictionary) { Frequencies = new FrequencyDictionary(); Frequencies = frequencyDictionary; //var startTime = System.Diagnostics.Stopwatch.StartNew(); BuildTree(Frequencies); //startTime.Stop(); //var resultTime = startTime.Elapsed; //string elapsedTime = String.Format("{0:00}:{1:00}:{2:00}.{3:000}", // resultTime.Hours, // resultTime.Minutes, // resultTime.Seconds, // resultTime.Milliseconds); //Console.WriteLine("Build tree: " + elapsedTime); //startTime = System.Diagnostics.Stopwatch.StartNew(); BuildCodeTable(Frequencies); //startTime.Stop(); //resultTime = startTime.Elapsed; //elapsedTime = String.Format("{0:00}:{1:00}:{2:00}.{3:000}", // resultTime.Hours, // resultTime.Minutes, // resultTime.Seconds, // resultTime.Milliseconds); //Console.WriteLine("Build code table: " + elapsedTime); //BuildCodeTable(Frequencies); }
public void Decode(string fileNameSource, string fileNameDecode) { BitArray bitArray = null; try { bitArray = new BitArray((File.ReadAllBytes(fileNameSource))); } catch (Exception exc) { throw exc; } //считываем длину битов декодировочной таблицы BitArray numBitCodeTable = new BitArray(32); for (int i = 0; i < 32; i++) { numBitCodeTable[i] = bitArray[i]; } byte[] num = new byte[4]; numBitCodeTable.CopyTo(num, 0); int lenTable = BitConverter.ToInt32(num, 0); Frequencies = GetFrequencyDictionaryFromFile(bitArray, 32, lenTable + 32); BuildTree(Frequencies); Decode(bitArray, lenTable + 32, fileNameDecode); }
/// <summary> /// Кодирование блока слов /// </summary> /// <param name="words">Блок слов определённого размера</param> /// <returns>Закодированый блок представленный списком битов</returns> public List <bool> EncodeBlock(List <string> words) { List <bool> encodedSource = new List <bool>(); //Составляем частотный словарь из блока слов FrequencyDictionary frequencyDictionary = new FrequencyDictionary(words); //Строим дерево по полученому словарю HuffmanTree huffmanTree = new HuffmanTree(frequencyDictionary); //Кодируем блок encodedSource = huffmanTree.EncodeBlock(words); //добавляем таблицу для декодировки List <bool> table = huffmanTree.GetBitArrayTable(frequencyDictionary); //получаем длину таблицы в виде массиве байтов //byte[] lenTable = BitConverter.GetBytes(table.Count); List <bool> lenghtTable = BitOperations.Int32ToListBool(table.Count); lenghtTable.AddRange(table); table = lenghtTable; //Добавляем код table.AddRange(encodedSource); //Получаем длину всего закодированного блока List <bool> lenghtAll = BitOperations.Int32ToListBool(table.Count); //добавляем эту длину в в начало блока lenghtAll.AddRange(table); encodedSource = lenghtAll; //возращаем закодированный блок return(encodedSource); }
//public string DecodeBlock(string fileNameEncode) //{ // BitArray bitArray = null; // try // { // bitArray = new BitArray((File.ReadAllBytes(fileNameEncode))); // } // catch (Exception exc) // { // throw exc; // } // string text = ""; // int indexStart = 0; // while(indexStart < bitArray.Count) // { // text += DecodeBlock(bitArray, indexStart, out indexStart); // } // return text; //} public string DecodeBlock(BitArray bits, int indexStart, out int indexStop) { int index = indexStart; string textBlock = ""; //Извдекаем всю длину блока вместе с диной //таблицы и последовательности кодов int lenAllBlock = HuffmanTree.GetIntFromBitArray(index, bits); index += sizeByte * sizeof(int); //Извлекаем длину таблицы int lenTable = HuffmanTree.GetIntFromBitArray(index, bits); index += sizeByte * sizeof(int); //получае частотный словарь с блока FrequencyDictionary frequencyDictionary = HuffmanTree.GetFrequencyDictionaryFromFile(bits, index, index + lenTable); index = index + lenTable; //получаем дерево и декодировучныю таблицу HuffmanTree huffmanTree = new HuffmanTree(frequencyDictionary); //Декодируем блок textBlock = huffmanTree.DecodeBlock(bits, index, index + ((lenAllBlock) - (lenTable + sizeof(int) * sizeByte))); indexStop = index + ((lenAllBlock) - (lenTable + sizeof(int) * sizeByte)); //indexStop = lenAllBlock + sizeof(int) * sizeByte; return(textBlock); }
public void BuildCodeTable(FrequencyDictionary frequencyDictionary) { CodeTable = new Dictionary <string, List <bool> >(); foreach (var wordNode in nodesDictionary) { List <bool> encodedWord = GetCode(wordNode.Value); //Root.Traverse(word.Key, new List<bool>()); CodeTable.Add(wordNode.Key, encodedWord); } }
/// <summary> /// Получить вектор с честотами для блока слов /// </summary> /// <param name="frequencyDictionary">Словарь всех слов текста</param> /// <param name="words">Блок слов</param> /// <returns>Вектор, с частотами слов в блоке</returns> public static Dictionary <string, double> GetVectorFrequencyFromBlock(FrequencyDictionary frequencyDictionary, List <string> words) { //Получаем нулевой вектор Dictionary <string, double> vector = GetVectorZerosFromFrequencyDictionary(frequencyDictionary); //подсчитываем количество слов foreach (var word in words) { vector[word] += 1; } List <string> keys = new List <string>(vector.Keys); //получаем частоту foreach (var item in keys) { vector[item] /= words.Count; } return(vector); }
public void BuildTree(FrequencyDictionary frequencyDictionary) { foreach (KeyValuePair <string, int> word in frequencyDictionary.Dictionary) { nodes.Add(new NodeHT() { Word = word.Key, Frequency = word.Value }); nodesDictionary.Add(word.Key, nodes.Last()); } while (nodes.Count > 1) { List <NodeHT> orderedNodes = nodes.OrderBy(node => node.Frequency).ToList <NodeHT>(); if (orderedNodes.Count >= 2) { // Take first two items List <NodeHT> taken = orderedNodes.Take(2).ToList(); // Create a parent node by combining the frequencies NodeHT parent = new NodeHT() { Word = "", Frequency = taken[0].Frequency + taken[1].Frequency, Left = taken[0], Right = taken[1] }; taken[0].Parent = parent; taken[1].Parent = parent; nodes.Remove(taken[0]); nodes.Remove(taken[1]); nodes.Add(parent); } Root = nodes.FirstOrDefault(); Root.Parent = null; } }
public HuffmanTree() { nodes = new List <NodeHT>(); Root = null; Frequencies = new FrequencyDictionary(); }
public List <bool> GetBitArrayTable(FrequencyDictionary frequencyDictionary) { List <bool> res = new List <bool>(); byte lenBitWord = 0x00; foreach (var item in frequencyDictionary.Dictionary) { lenBitWord = (byte)item.Key.Length; for (int i = 0; i < 8; i++) { if (((lenBitWord << i) & maskForEncode) == 0x00) { res.Add(false); } else { res.Add(true); } } byte[] wordByteArray = Encoding.Default.GetBytes(item.Key); foreach (var symbol in wordByteArray) { for (int i = 0; i < 8; i++) { if ((byte)((symbol << i) & maskForEncode) == 0x00) { res.Add(false); } else { res.Add(true); } } } byte[] buf = BitConverter.GetBytes(item.Value); byte[] freq = new byte[4]; freq = buf; //for (int i = 0; i < buf.Length; i++) //{ // freq[i] = buf[buf.Length - 1 - i]; //} foreach (var b in freq) { for (int i = 0; i < 8; i++) { if (((b << i) & maskForEncode) == 0x00) { res.Add(false); } else { res.Add(true); } } } } //if(codeTableBit.Count % 8 == 0) return(res); }
/// <summary> /// Получение нулевого вектора, для текста /// </summary> /// <param name="frequencyDictionary">Частотный словарь по всему тексту</param> /// <returns>Нулевой вектор, где каждое слово ассоциируется с конкретной позицией в векторе</returns> public static Dictionary <string, double> GetVectorZerosFromFrequencyDictionary(FrequencyDictionary frequencyDictionary) { Dictionary <string, double> vector = new Dictionary <string, double>(); //Отсортируем по частоте встречания слова frequencyDictionary.SortDescValue(); //Вормируем ассоциативный 0-вектор foreach (var item in frequencyDictionary.Dictionary) { vector.Add(item.Key, 0.0); } return(vector); }
/// <summary> /// Кодирование исходного текста блочным способом c использованием метрики /// </summary> /// <param name="fileNameSource">Имя файла исходного текста</param> /// <param name="sizeBlock">Размер блока</param> /// <returns>Закодированый текст блочным методом с использованием метрики, представленный в виде списка битов</returns> public List <bool> EncodeBlockWithMetrics(string fileNameSource, int sizeBlock, out List <double> distanсeEuclide, out List <double> distanceChebyshev, out List <double> distanceCityBlock) { FrequencyDictionary frequencyDictionary = new FrequencyDictionary(fileNameSource); Dictionary <string, double> p = ComparisonVector.GetVectorZerosFromFrequencyDictionary(frequencyDictionary); Dictionary <string, double> q = ComparisonVector.GetVectorZerosFromFrequencyDictionary(frequencyDictionary); List <double> distanceE = new List <double>(); List <double> distanceC = new List <double>(); List <double> distanceCB = new List <double>(); //Открываем поток для считывания с файла StreamReader fileRead = new StreamReader(@fileNameSource, Encoding.Default); List <bool> encodedSource = new List <bool>(); //Считываем весь текст с файла string text = fileRead.ReadToEnd(); //int indexText = 0; int indexBegin = 0; int indexEnd = 0; //пока не конец текста while (indexEnd < text.Length) { //indexBegin = 0; //indexEnd = 0; List <string> listWords = new List <string>(); //идём по тексту, пока не наберём слов количеством в размер блока и пока не конец текста for (int i = 0; (i < sizeBlock) && (indexEnd < text.Length); i++) { //пока это буква увеличиваем индекс конца слова while (indexEnd < text.Length && char.IsLetter(text[indexEnd]) /*((text[indexEnd] >= 'a' && text[indexEnd] <= 'z') || * (text[indexEnd] >= 'A' && text[indexEnd] <= 'Z')) || * ((text[indexEnd] >= 'а' && text[indexEnd] <= 'я') || * (text[indexEnd] >= 'А' && text[indexEnd] <= 'Я'))*/) { indexEnd++; } //если мы прошлись по слову string word; if (indexBegin != indexEnd) { word = text.Substring(indexBegin, indexEnd - indexBegin); } else //это знак препенания, пробел или знак табуляции { indexEnd++; word = text.Substring(indexBegin, indexEnd - indexBegin); } indexBegin = indexEnd; //добавляем слово в блок listWords.Add(word); } //кодирум блок слов и добавляем получившиеся биты в список битов encodedSource.AddRange(EncodeBlock(listWords)); //работа с растояниями q = ComparisonVector.GetVectorFrequencyFromBlock(frequencyDictionary, listWords); distanceE.Add(ComparisonVector.GetEuclideanDistance(p, q)); distanceC.Add(ComparisonVector.GetChebyshevDistance(p, q)); distanceCB.Add(ComparisonVector.GetCityBlockDistance(p, q)); p = q; } //for (int i = 0; i < distanceE.Count; i++) //{ // Console.Write(distanceE[i].ToString() + " " + distanceC[i].ToString() + // " " + distanceCB[i].ToString() + "\n"); //} distanсeEuclide = distanceE; distanceChebyshev = distanceC; distanceCityBlock = distanceCB; //возращаем закодированный блок слов в виде списка бит return(encodedSource); }