// the private contructor for the class // den private contructor for denne klasse private JSONAbleHuffmanNode(HuffmanNode node) { // symbol is symbol, since a string is normal for json // symbol er symbol, eftersom at en tekststreng er normalt for json symbol = node.Symbol; // code is a string instead of an bit array, this is more json friendly // code bliver konvertede til en tekststren for at være json venlig code = node.Code.Print(); // right and left tree, is converted recursively // højere og venstre node er konverteret rekursivt leftTree = Parse(node.LeftChildNode); rightTree = Parse(node.RightChildNode); //leaf is just leaf //et blad er et blad isLeaf = node.IsLeaf; }
// this is a recursive method to print the information, but not as a tree like the last one public void PrintInformation(HuffmanNode node = null) { // if node is null use the root if (node == null) { node = Root; } // print the symbol, code and frequency Console.WriteLine("Symbol : " + node.Symbol + " - Code : " + node.Code.Print() + " - Frequency : " + node.Frequency); // if it is not a leaf call the function recursivly for left and right if (!node.IsLeaf) { PrintInformation(node.LeftChildNode); PrintInformation(node.RightChildNode); } }
// this is a recursive method to print the information, but only the leafs public void PrintfLeafAndCodes(HuffmanNode node = null) { // if node is null use the root if (node == null) { node = Root; } // if there is no left and right node, print the symbol, code and frequency. Then return if (node.LeftChildNode == null && node.RightChildNode == null) { Console.WriteLine("Symbol : " + node.Symbol + " - Code : " + node.Code.Print() + " - Frequency : " + node.Frequency); return; } // recursivly call this method for the left and right node PrintfLeafAndCodes(node.LeftChildNode); PrintfLeafAndCodes(node.RightChildNode); }
// this is a recursive method to print the information, but not as a tree like the last one // Dette er en rekursiv funktion for at udskrive den information, men ikke som et træ ligesom før public void PrintInformation(HuffmanNode node = null) { // if node is null use the root // Hvis noden er null benyttes roden if (node == null) { node = Root; } // print the symbol, code and frequency // Udskriv symbolet, koden og frekvensen Console.WriteLine("Symbol : " + node.Symbol + " - Code : " + node.Code.Print() + " - Frequency : " + node.Frequency); // if it is not a leaf call the function recursivly for left and right // Hvis det ikker er et blad kaldes den funktion rekursivt for venstre og højre side if (!node.IsLeaf) { PrintInformation(node.LeftChildNode); PrintInformation(node.RightChildNode); } }
// this is a recursive method to print the information, but only the leafs // Dette er en rekursiv funktion for at udskrive den information, men kun de venstre blade public void PrintfLeafAndCodes(HuffmanNode node = null) { // if node is null use the root // Hvis noden er null benyttes roden if (node == null) { node = Root; } // if there is no left and right node, print the symbol, code and frequency. Then return // Hvis der ikke er nogen venstre node, udskriv symbolet, koden og frekvensen. Derefter returner if (node.LeftChildNode == null && node.RightChildNode == null) { Console.WriteLine("Symbol : " + node.Symbol + " - Code : " + node.Code.Print() + " - Frequency : " + node.Frequency); return; } // recursivly call this method for the left and right node // Rekursivt kald denne funktion for den venstre og højre node PrintfLeafAndCodes(node.LeftChildNode); PrintfLeafAndCodes(node.RightChildNode); }
/// <summary> /// Traverse the tree while setting the Path values of each node /// </summary> /// <param name="root"></param> /// <param name="recursionDepth"></param> /// <param name="path"></param> private void SetCodes(HuffmanNode root = null, int recursionDepth = 0, string path = "") { if (root == null) { if (recursionDepth == 0) { root = Root; } else { return; } } root.Path = new BitArray(path .Select(x => x == '1') .ToArray()); SetCodes(root.Left, ++recursionDepth, path + "0"); SetCodes(root.Right, ++recursionDepth, path + "1"); }
/// <summary> /// Recursively search a specific value in the tree /// </summary> /// <param name="value">The value to be searched for.</param> /// <param name="root">The root <see cref="HuffmanNode"/> from where the search begins.</param> /// <param name="recursionDepth">Specifies how deep we are in the call stack. /// It lets us decide whether it has been called for the first time or are we /// deeper in the call stack. /// </param> /// <returns>The corresponding node with the value or null if there isn't such node.</returns> public HuffmanNode Search(int value, HuffmanNode root = null, int recursionDepth = 0) { if (root == null) { if (recursionDepth == 0) { root = Root; } else { return(null); } } if (root.Value == value) { return(root); } recursionDepth++; return(Search(value, root.Left) ?? Search(value, root.Right, recursionDepth)); }
// this is a recursive method to print the tree public void PrintTree(int level, HuffmanNode node = null) { // if node is null use the root if (node == null) { node = Root; } // print a tab for every level for (int i = 0; i < level; i++) { Console.Write("\t"); } // print the symbol Console.Write("[" + node.Symbol + "]"); // set color SetColor(); // print the code Console.WriteLine("(" + node.Code.Print() + ")"); // set the color back to default SetColorDefault(); // call this method recursivly with the right and left node, and on more level PrintTree(level + 1, node.RightChildNode); PrintTree(level + 1, node.LeftChildNode); }
// The constructor sets the Root property, based on its argument public HuffmanTree(HuffmanNode node) { Root = node; }
// this method creates a tree based on text public static HuffmanTree CreateFromText(string text) { // the list that we wanna fill up with nodes List <HuffmanNode> nodeList = new List <HuffmanNode>(); // all the characters from the text char[] characters = text.ToCharArray(); // loop thought the characters for (int i = 0; i < characters.Length; i++) { // the character as a string string read = characters[i].ToString(); // has the node already been created? if (nodeList.Exists(x => x.Symbol == read)) { // If is yes, find the index of the Node and increase the frequency of the Node. nodeList[nodeList.FindIndex(y => y.Symbol == read)].Frequency++; } else { // If is no, create a new node and add to the List of Nodes nodeList.Add(new HuffmanNode(read)); } } // sort them, this is done based on frequency because of IComparable<HuffmanNode>.CompareTo nodeList.Sort(); // loop thought them, until only one is left while (nodeList.Count > 1) { // Get the node of the first index of List, this is the one with the lowest frequency HuffmanNode node1 = nodeList[0]; // and delete it. nodeList.RemoveAt(0); // do the same thing again HuffmanNode node2 = nodeList[0]; nodeList.RemoveAt(0); // make a parant node with node1 and node2 and the left and right child nodes nodeList.Add(new HuffmanNode(node1, node2)); // and sort it again according to frequency. nodeList.Sort(); } // create a tree based on the remaining root node HuffmanTree tree = new HuffmanTree(nodeList[0]); // this is a recursive function to set the binary code of every leaf node void setCodeToTheTree(HuffmanNode Nodes, BitArray code = null) { // if the current code is not set, set it to an empty BitArray if (code == null) { code = new BitArray(new bool[] { }); } // if the code is empty do nothing if (Nodes == null) { return; } // if there is no left node and right node, then set the code based on the current code if (Nodes.LeftChildNode == null && Nodes.RightChildNode == null) { Nodes.Code = code; return; } // create a bitlist for the left node BitList left = BitList.Parse(code); // add false for the left side left.Add(false); // call this function recursively, with the left bitlist and the left side node setCodeToTheTree(Nodes.LeftChildNode, left.ToBitArray()); // create a bitlist for the right node BitList right = BitList.Parse(code); // add true for the right side right.Add(true); // call the function recursively, with the right bitlist and the right side node setCodeToTheTree(Nodes.RightChildNode, right.ToBitArray()); } // call the recursive function setCodeToTheTree(tree.Root); // the tree return(tree); }
// this method creates a tree based on text // Denne funktion laver et træ baseret på tekst public static HuffmanTree CreateFromText(string text) { // the list that we wanna fill up with nodes // Listen der skal fyldes med noder List <HuffmanNode> nodeList = new List <HuffmanNode>(); // all the characters from the text // Alle symbolerne fra teksten char[] characters = text.ToCharArray(); // loop thought the characters // Gentag igennem symbolerne for (int i = 0; i < characters.Length; i++) { // the character as a string // Symbolerne som strenge string read = characters[i].ToString(); // has the node already been created? // Er noden allerede blevet skabt? if (nodeList.Exists(x => x.Symbol == read)) { // If is yes, find the index of the Node and increase the frequency of the Node. // Hvis ja, find indekset for noden og øg frekvensen for node nodeList[nodeList.FindIndex(y => y.Symbol == read)].Frequency++; } else { // If is no, create a new node and add to the List of Nodes // Hvis nej, skab en ny node og tilføj den til listen over node nodeList.Add(new HuffmanNode(read)); } } // sort them, this is done based on frequency because of IComparable<HuffmanNode>.CompareTo // Sorter dem, dette gøres baseret på frekvens fordi at IComparable<HuffmanNode>.CompareTo nodeList.Sort(); // loop thought them, until only one is left // Kør igennem dem alle sammen indtil der kun er en tilbage while (nodeList.Count > 1) { // Get the node of the first index of List, this is the one with the lowest frequency // Få noden for det første indeks af Listen, dette er den med den laveste frekvens HuffmanNode node1 = nodeList[0]; // and delete it. // Fjern den nodeList.RemoveAt(0); // do the same thing again // Gør det samme igen HuffmanNode node2 = nodeList[0]; nodeList.RemoveAt(0); // make a parant node with node1 and node2 and the left and right child nodes // Lav en parent-node med node1 og node1 og de venstre og højre child-noder nodeList.Add(new HuffmanNode(node1, node2)); // and sort it again according to frequency. // Og sorter det igen efter frekvens nodeList.Sort(); } // create a tree based on the remaining root node // Lav et træ baseret på den tilbageværende rod-node HuffmanTree tree = new HuffmanTree(nodeList[0]); // this is a recursive function to set the binary code of every leaf node // Dette er en rekursiv funktion for at sætte den binære værdi for hvert blad void setCodeToTheTree(HuffmanNode Nodes, BitArray code = null) { // if the current code is not set, set it to an empty BitArray // Hvis den nuværende kode ikke er sat, sættes den til et tomt BitArray if (code == null) { code = new BitArray(new bool[] { }); } // if the code is empty do nothing // Hvis koden er tom, gør intet if (Nodes == null) { return; } // if there is no left node and right node, then set the code based on the current code // Hvis der ikke er nogen venstre node, sæt koden baseret på den nuværende kode if (Nodes.LeftChildNode == null && Nodes.RightChildNode == null) { Nodes.Code = code; return; } // create a bitlist for the left node // lav en bitliste for den venstre node BitList left = BitList.Parse(code); // add false for the left side // tilføj false for den venstre side left.Add(false); // call this function recursively, with the left bitlist and the left side node // Kald denne funktion rekursivt, med den venstre bitliste og den venstre node setCodeToTheTree(Nodes.LeftChildNode, left.ToBitArray()); // create a bitlist for the right node // Lav en bitliste for den højre node BitList right = BitList.Parse(code); // add true for the right side // tilføj true for den højre side right.Add(true); // call the function recursively, with the right bitlist and the right side node // Kald denne funktion rekursivt, med den højre bitliste og den højre node setCodeToTheTree(Nodes.RightChildNode, right.ToBitArray()); } // call the recursive function // Kald den rekursive funktion setCodeToTheTree(tree.Root); // the tree // Træet returneres return(tree); }
// This method decodes bytes into a string, based on the current huffman tree // Essentially, the opposite of the one above // Denne funktion afkoder bytes til en string, baseret på det nuværende Huffman-træ // Stort set bare det foregående baglæns public string Decode(byte[] encoded) { // Turn the bytes into bits, and make a list of them // Bytes omdannes til bits, og der laves en liste af dem BitList bits = BitList.Parse(new BitArray(encoded)); // a recursive function to remove the ending of the bits // the ending is there, only to make sure that the length of the list is divisible by 8 // this function therefore removes 0 from the end, until it hits a 1, which is then removed, and the function stops // En rekursiv funktion for at fjerne enderne på bits // Enderne er der kun for at sikre at længden på listen kan divideres med 8 // Denne funktion fjerner derfor 0'er fra enden, indtil at den rammer et 1, hvilket derefter fjernes og funktionen stopper void clean(BitList list) { //if it is a 1 // Hvis det er et 1 if (list[list.Count - 1]) { // remove the 1 // Fjern 1 list.RemoveAt(list.Count - 1); } // if it is a 0 // Hvis det er et 0 else { // remove the 0 // Fjern 0 list.RemoveAt(list.Count - 1); // repeat // Gentag clean(list); } } // call the function just described // Kald funktionen fra før clean(bits); // init the string that is going to hold the decoded string // strengen der skal indehold den afkodede streng laves string str = ""; // define a variable to hold the current node that we are on // Der defineres en variabel til at holde det nuværende node der kigges på HuffmanNode currentNode = Root; // loop thought all the bits // Kør igennem alle bits for (int i = 0; i < bits.Count; i++) { // if it is a 1, take the right node // Hvis det er et 1, tag højre node if (bits[i]) { currentNode = currentNode.RightChildNode; } // if it is a 0, take the left node // Hvis det er et 0, tag venstre node else { currentNode = currentNode.LeftChildNode; } // if the current node is a leaf // Hvis den nuværende node er et blad if (currentNode.IsLeaf) { // add the symbol to the str variable // Tilføj symbolet til streng-variablen "str" str += currentNode.Symbol; // go back to the root of the tree // Gå tilbage til træets rod currentNode = Root; } } ; // return the decoded symbols // Returner de afkodede symboler return(str); }