From 85424b99d40ad85d78f73281de20a2152ab66b8d Mon Sep 17 00:00:00 2001 From: Julian Schacher Date: Thu, 19 Apr 2018 02:04:27 +0200 Subject: [PATCH 1/7] Add Huffman in C#. --- .../huffman/code/cs/HuffmanCoding.cs | 185 ++++++++++++++++++ .../huffman/code/cs/Program.cs | 40 ++++ chapters/data_compression/huffman/huffman.md | 6 + 3 files changed, 231 insertions(+) create mode 100644 chapters/data_compression/huffman/code/cs/HuffmanCoding.cs create mode 100644 chapters/data_compression/huffman/code/cs/Program.cs diff --git a/chapters/data_compression/huffman/code/cs/HuffmanCoding.cs b/chapters/data_compression/huffman/code/cs/HuffmanCoding.cs new file mode 100644 index 000000000..1b90b7e9e --- /dev/null +++ b/chapters/data_compression/huffman/code/cs/HuffmanCoding.cs @@ -0,0 +1,185 @@ +// submitted by Julian Schacher (jspp) +using System; +using System.Collections.Generic; +using System.Linq; + +namespace HuffmanCoding +{ + public class EncodeResult + { + public List BitString { get; set; } + public Dictionary> Dictionary { get; set; } + public HuffmanCoding.Node Tree { get; set; } + + public EncodeResult(List bitString, Dictionary> dictionary, HuffmanCoding.Node tree) + { + this.BitString = bitString; + this.Dictionary = dictionary; + this.Tree = tree; + } + } + + public static class HuffmanCoding + { + // The Node class used for the Huffman Tree. + public class Node + { + public Node[] Children { get; set; } = new Node[2]; + public List BitString { get; set; } = new List(); + public int Weight { get; set; } + public string Key { get; set; } + + public Node(string key, int weight) + { + this.Key = key; + this.Weight = weight; + } + } + + // Node with biggest value at the top. + class NodePriorityList + { + public List Nodes { get; private set; } = new List(); + + public NodePriorityList() { } + public NodePriorityList(List nodes) => Nodes = nodes.OrderByDescending(n => n.Weight).ToList(); + + public void AddNode(Node newNode) + { + if (Nodes.Count == 0) + { + Nodes.Add(newNode); + return; + } + for (int i = Nodes.Count - 1; i >= 0; i--) + { + if (Nodes[i].Weight > newNode.Weight) + { + Nodes.Insert(i + 1, newNode); + return; + } + else if (i == 0) + Nodes.Insert(0, newNode); + } + } + } + + public static EncodeResult Encode(string input) + { + var root = CreateTree(input); + var dictionary = CreateDictionary(root); + var bitString = CreateBitString(input, dictionary); + + return new EncodeResult(bitString, dictionary, root); + } + + public static string Decode(EncodeResult result) + { + var output = ""; + Node currentNode = result.Tree; + foreach (var boolean in result.BitString) + { + // Go down the tree. + if (!boolean) + currentNode = currentNode.Children[0]; + else + currentNode = currentNode.Children[1]; + + // Check if it's a leaf node. + if (currentNode.Key.Count() == 1) + { + output += currentNode.Key; + currentNode = result.Tree; + } + } + return output; + } + + private static Node CreateTree(string input) + { + // Create a List of all characters and their count in input by putting them into nodes. + var nodes = new List(); + foreach (var character in input) + { + var result = nodes.Where(n => n.Key[0] == character).SingleOrDefault(); + + if (result == null) + nodes.Add(new Node(character.ToString(), 1)); + else + result.Weight++; + } + // Convert list of nodes to a NodePriorityList. + var nodePriorityList = new NodePriorityList(nodes); + nodes = nodePriorityList.Nodes; + + // Create Tree. + while (nodes.Count > 1) + { + var parentNode = new Node("", 0); + // Add the two nodes with the smallest weight to the parent node and remove them from the tree. + for (int i = 0; i < 2; i++) + { + parentNode.Children[i] = nodes.Last(); + parentNode.Key += nodes.Last().Key; + parentNode.Weight += nodes.Last().Weight; + + nodes.RemoveAt(nodes.Count - 1); + }; + nodePriorityList.AddNode(parentNode); + if (parentNode.Weight > 100) + throw new Exception(); + } + + return nodePriorityList.Nodes[0]; + } + + private static Dictionary> CreateDictionary(Node root) + { + var dictionary = new Dictionary>(); + + var stack = new Stack(); + stack.Push(root); + Node temp; + + while (stack.Count != 0) + { + temp = stack.Pop(); + + if (temp.Key.Count() == 1) + dictionary.Add(temp.Key[0], temp.BitString); + else + { + for (int i = 0; i < temp.Children.Count(); i++) + { + if (temp.Children[i] != null) + { + if (i == 0) + { + temp.Children[i].BitString.AddRange(temp.BitString); + temp.Children[i].BitString.Add(false); + } + else + { + temp.Children[i].BitString.AddRange(temp.BitString); + temp.Children[i].BitString.Add(true); + } + + stack.Push(temp.Children[i]); + } + } + } + } + + return dictionary; + } + + private static List CreateBitString(string input, Dictionary> dictionary) + { + var bitString = new List(); + foreach (var character in input) + bitString.AddRange(dictionary[character]); + + return bitString; + } + } +} \ No newline at end of file diff --git a/chapters/data_compression/huffman/code/cs/Program.cs b/chapters/data_compression/huffman/code/cs/Program.cs new file mode 100644 index 000000000..9f75ccb17 --- /dev/null +++ b/chapters/data_compression/huffman/code/cs/Program.cs @@ -0,0 +1,40 @@ +// submitted by Julian Schacher (jspp) +using System.Collections; +using System.Collections.Generic; + +namespace HuffmanCoding +{ + class Program + { + static void Main(string[] args) + { + var result = HuffmanCoding.Encode("aaaabbbccd"); + // Print dictionary. + foreach (var entry in result.Dictionary) + { + var bitString = ""; + foreach (var value in entry.Value) + { + if (value) + bitString += "1"; + else + bitString += "0"; + } + System.Console.WriteLine(entry.Key + " " + bitString); + } + // Print bitString. + var readableBitString = ""; + foreach (var boolean in result.BitString) + { + if (boolean) + readableBitString += "1"; + else + readableBitString += "0"; + } + System.Console.WriteLine(readableBitString); + + var originalString = HuffmanCoding.Decode(result); + System.Console.WriteLine(originalString); + } + } +} \ No newline at end of file diff --git a/chapters/data_compression/huffman/huffman.md b/chapters/data_compression/huffman/huffman.md index 50c4c0eb5..896b6ee9f 100644 --- a/chapters/data_compression/huffman/huffman.md +++ b/chapters/data_compression/huffman/huffman.md @@ -86,4 +86,10 @@ Whether you use a stack or straight-up recursion also depends on the language, b {% sample lang="hs" %} ### Haskell [import, lang:"haskell"](code/haskell/huffman.hs) +{% sample lang="cs" %} +### C# # +HuffmanCoding.cs +[import, lang:"csharp"](code/cs/HuffmanCoding.cs) +Program.cs +[import, lang:"csharp"](code/cs/Program.cs) {% endmethod %} From d91ea9eab536fa65d91af79ab87c9baddee08a6e Mon Sep 17 00:00:00 2001 From: Julian Schacher Date: Mon, 7 May 2018 01:49:48 +0200 Subject: [PATCH 2/7] Rename EncodeResult to EncodingResult. Remove lines left over from debugging. Add mention. --- .../huffman/code/cs/HuffmanCoding.cs | 14 ++++++-------- .../data_compression/huffman/code/cs/Program.cs | 2 +- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/chapters/data_compression/huffman/code/cs/HuffmanCoding.cs b/chapters/data_compression/huffman/code/cs/HuffmanCoding.cs index 1b90b7e9e..6859ca7e8 100644 --- a/chapters/data_compression/huffman/code/cs/HuffmanCoding.cs +++ b/chapters/data_compression/huffman/code/cs/HuffmanCoding.cs @@ -1,17 +1,17 @@ -// submitted by Julian Schacher (jspp) +// submitted by Julian Schacher (jspp) with help by gustorn. using System; using System.Collections.Generic; using System.Linq; namespace HuffmanCoding { - public class EncodeResult + public class EncodingResult { public List BitString { get; set; } public Dictionary> Dictionary { get; set; } public HuffmanCoding.Node Tree { get; set; } - public EncodeResult(List bitString, Dictionary> dictionary, HuffmanCoding.Node tree) + public EncodingResult(List bitString, Dictionary> dictionary, HuffmanCoding.Node tree) { this.BitString = bitString; this.Dictionary = dictionary; @@ -64,16 +64,16 @@ public void AddNode(Node newNode) } } - public static EncodeResult Encode(string input) + public static EncodingResult Encode(string input) { var root = CreateTree(input); var dictionary = CreateDictionary(root); var bitString = CreateBitString(input, dictionary); - return new EncodeResult(bitString, dictionary, root); + return new EncodingResult(bitString, dictionary, root); } - public static string Decode(EncodeResult result) + public static string Decode(EncodingResult result) { var output = ""; Node currentNode = result.Tree; @@ -126,8 +126,6 @@ private static Node CreateTree(string input) nodes.RemoveAt(nodes.Count - 1); }; nodePriorityList.AddNode(parentNode); - if (parentNode.Weight > 100) - throw new Exception(); } return nodePriorityList.Nodes[0]; diff --git a/chapters/data_compression/huffman/code/cs/Program.cs b/chapters/data_compression/huffman/code/cs/Program.cs index 9f75ccb17..ce780f799 100644 --- a/chapters/data_compression/huffman/code/cs/Program.cs +++ b/chapters/data_compression/huffman/code/cs/Program.cs @@ -1,4 +1,4 @@ -// submitted by Julian Schacher (jspp) +// submitted by Julian Schacher (jspp) with help by gustorn. using System.Collections; using System.Collections.Generic; From 5d5089a85b8efb8d9eb5309da08e5c3ee5908128 Mon Sep 17 00:00:00 2001 From: Julian Schacher Date: Mon, 28 May 2018 04:15:27 +0200 Subject: [PATCH 3/7] Replace children array with left and right child. Write the count of the readableBitString to console. Have Node implement IComparable and improve the code according to that. Improve the creation of the initial list of nodes. Refactor NodePriorityList. Improve Node creation. --- .../huffman/code/cs/HuffmanCoding.cs | 116 +++++++++--------- .../huffman/code/cs/Program.cs | 2 +- 2 files changed, 58 insertions(+), 60 deletions(-) diff --git a/chapters/data_compression/huffman/code/cs/HuffmanCoding.cs b/chapters/data_compression/huffman/code/cs/HuffmanCoding.cs index 6859ca7e8..67662c37d 100644 --- a/chapters/data_compression/huffman/code/cs/HuffmanCoding.cs +++ b/chapters/data_compression/huffman/code/cs/HuffmanCoding.cs @@ -22,45 +22,60 @@ public EncodingResult(List bitString, Dictionary> diction public static class HuffmanCoding { // The Node class used for the Huffman Tree. - public class Node + public class Node : IComparable { - public Node[] Children { get; set; } = new Node[2]; + public Node LeftChild { get; set; } + public Node RightChild { get; set; } public List BitString { get; set; } = new List(); public int Weight { get; set; } public string Key { get; set; } - - public Node(string key, int weight) + + // Creates a leaf. So just a node is created with the given values. + public static Node CreateLeaf(char key, int weight) => new Node(key.ToString(), weight, null, null); + // Creates a branch. Here a node is created by adding the keys and weights of both childs together. + public static Node CreateBranch(Node leftChild, Node rightChild) => new Node(leftChild.Key + rightChild.Key, leftChild.Weight + rightChild.Weight, leftChild, rightChild); + private Node(string key, int weight, Node leftChild, Node rightChild) { this.Key = key; this.Weight = weight; + this.LeftChild = leftChild; + this.RightChild = rightChild; } + + public int CompareTo(Node other) => this.Weight - other.Weight; } // Node with biggest value at the top. class NodePriorityList { - public List Nodes { get; private set; } = new List(); + public int Count => nodes.Count; + + private List nodes = new List(); public NodePriorityList() { } - public NodePriorityList(List nodes) => Nodes = nodes.OrderByDescending(n => n.Weight).ToList(); + public NodePriorityList(List givenNodes) + { + this.nodes = givenNodes.ToList(); + this.nodes.Sort(); + } - public void AddNode(Node newNode) + public void Add(Node newNode) { - if (Nodes.Count == 0) + var index = ~this.nodes.BinarySearch(newNode); + if (index == this.nodes.Count) { - Nodes.Add(newNode); + this.nodes.Add(newNode); return; } - for (int i = Nodes.Count - 1; i >= 0; i--) - { - if (Nodes[i].Weight > newNode.Weight) - { - Nodes.Insert(i + 1, newNode); - return; - } - else if (i == 0) - Nodes.Insert(0, newNode); - } + this.nodes.Insert(~index, newNode); + } + + public Node Pop() + { + var first = this.nodes.First(); + if (first != null) + this.nodes.Remove(first); + return first; } } @@ -81,9 +96,9 @@ public static string Decode(EncodingResult result) { // Go down the tree. if (!boolean) - currentNode = currentNode.Children[0]; + currentNode = currentNode.LeftChild; else - currentNode = currentNode.Children[1]; + currentNode = currentNode.RightChild; // Check if it's a leaf node. if (currentNode.Key.Count() == 1) @@ -98,37 +113,26 @@ public static string Decode(EncodingResult result) private static Node CreateTree(string input) { // Create a List of all characters and their count in input by putting them into nodes. - var nodes = new List(); - foreach (var character in input) - { - var result = nodes.Where(n => n.Key[0] == character).SingleOrDefault(); + var nodes = input + .GroupBy(c => c) + .Select(n => Node.CreateLeaf(n.Key, n.Count())) + .ToList(); - if (result == null) - nodes.Add(new Node(character.ToString(), 1)); - else - result.Weight++; - } // Convert list of nodes to a NodePriorityList. var nodePriorityList = new NodePriorityList(nodes); - nodes = nodePriorityList.Nodes; // Create Tree. - while (nodes.Count > 1) + while (nodePriorityList.Count > 1) { - var parentNode = new Node("", 0); - // Add the two nodes with the smallest weight to the parent node and remove them from the tree. - for (int i = 0; i < 2; i++) - { - parentNode.Children[i] = nodes.Last(); - parentNode.Key += nodes.Last().Key; - parentNode.Weight += nodes.Last().Weight; + // Pop the two nodes with the smallest weights from the nodePriorityList and create a parentNode with the CreateBranch method. (This method adds the keys and weights of the childs together.) + var leftChild = nodePriorityList.Pop(); + var rightChild = nodePriorityList.Pop(); + var parentNode = Node.CreateBranch(leftChild, rightChild); - nodes.RemoveAt(nodes.Count - 1); - }; - nodePriorityList.AddNode(parentNode); + nodePriorityList.Add(parentNode); } - return nodePriorityList.Nodes[0]; + return nodePriorityList.Pop(); } private static Dictionary> CreateDictionary(Node root) @@ -147,23 +151,17 @@ private static Dictionary> CreateDictionary(Node root) dictionary.Add(temp.Key[0], temp.BitString); else { - for (int i = 0; i < temp.Children.Count(); i++) + if (temp.LeftChild != null) + { + temp.LeftChild.BitString.AddRange(temp.BitString); + temp.LeftChild.BitString.Add(false); + stack.Push(temp.LeftChild); + } + if (temp.RightChild != null) { - if (temp.Children[i] != null) - { - if (i == 0) - { - temp.Children[i].BitString.AddRange(temp.BitString); - temp.Children[i].BitString.Add(false); - } - else - { - temp.Children[i].BitString.AddRange(temp.BitString); - temp.Children[i].BitString.Add(true); - } - - stack.Push(temp.Children[i]); - } + temp.RightChild.BitString.AddRange(temp.BitString); + temp.RightChild.BitString.Add(true); + stack.Push(temp.RightChild); } } } diff --git a/chapters/data_compression/huffman/code/cs/Program.cs b/chapters/data_compression/huffman/code/cs/Program.cs index ce780f799..09cc23dcb 100644 --- a/chapters/data_compression/huffman/code/cs/Program.cs +++ b/chapters/data_compression/huffman/code/cs/Program.cs @@ -31,7 +31,7 @@ static void Main(string[] args) else readableBitString += "0"; } - System.Console.WriteLine(readableBitString); + System.Console.WriteLine($"{readableBitString} count: {readableBitString.Length}"); var originalString = HuffmanCoding.Decode(result); System.Console.WriteLine(originalString); From 664e3f9c04a82e698af79e01eb879988b9c0a607 Mon Sep 17 00:00:00 2001 From: Julian Schacher Date: Tue, 29 May 2018 01:59:34 +0200 Subject: [PATCH 4/7] Use a string instead of a List. Also add comments explaining why we're not using something like a BitArray. Change the name of the enumerator "boolean" to "bit". Fix the Pop method by using "this.nodes[0]" instead of "this.nodes.First()". Improve the way to find out, if a Node is a Leaf. --- .../huffman/code/cs/HuffmanCoding.cs | 46 ++++++++++--------- .../huffman/code/cs/Program.cs | 23 ++-------- 2 files changed, 28 insertions(+), 41 deletions(-) diff --git a/chapters/data_compression/huffman/code/cs/HuffmanCoding.cs b/chapters/data_compression/huffman/code/cs/HuffmanCoding.cs index 67662c37d..3b142a1d7 100644 --- a/chapters/data_compression/huffman/code/cs/HuffmanCoding.cs +++ b/chapters/data_compression/huffman/code/cs/HuffmanCoding.cs @@ -7,11 +7,11 @@ namespace HuffmanCoding { public class EncodingResult { - public List BitString { get; set; } - public Dictionary> Dictionary { get; set; } + public string BitString { get; set; } + public Dictionary Dictionary { get; set; } public HuffmanCoding.Node Tree { get; set; } - public EncodingResult(List bitString, Dictionary> dictionary, HuffmanCoding.Node tree) + public EncodingResult(string bitString, Dictionary dictionary, HuffmanCoding.Node tree) { this.BitString = bitString; this.Dictionary = dictionary; @@ -26,9 +26,11 @@ public class Node : IComparable { public Node LeftChild { get; set; } public Node RightChild { get; set; } - public List BitString { get; set; } = new List(); + public string BitString { get; set; } = ""; public int Weight { get; set; } public string Key { get; set; } + + public bool IsLeaf => LeftChild == null && RightChild == null; // Creates a leaf. So just a node is created with the given values. public static Node CreateLeaf(char key, int weight) => new Node(key.ToString(), weight, null, null); @@ -72,10 +74,9 @@ public void Add(Node newNode) public Node Pop() { - var first = this.nodes.First(); - if (first != null) - this.nodes.Remove(first); - return first; + var result = this.nodes[0]; + this.nodes.RemoveAt(0); + return result; } } @@ -92,16 +93,15 @@ public static string Decode(EncodingResult result) { var output = ""; Node currentNode = result.Tree; - foreach (var boolean in result.BitString) + foreach (var bit in result.BitString) { // Go down the tree. - if (!boolean) + if (bit == '0') currentNode = currentNode.LeftChild; else currentNode = currentNode.RightChild; - // Check if it's a leaf node. - if (currentNode.Key.Count() == 1) + if (currentNode.IsLeaf) { output += currentNode.Key; currentNode = result.Tree; @@ -135,9 +135,10 @@ private static Node CreateTree(string input) return nodePriorityList.Pop(); } - private static Dictionary> CreateDictionary(Node root) + private static Dictionary CreateDictionary(Node root) { - var dictionary = new Dictionary>(); + // We're using a string instead of a actual bits here, since it makes the code somewhat more readable and this is an educational example. + var dictionary = new Dictionary(); var stack = new Stack(); stack.Push(root); @@ -147,20 +148,20 @@ private static Dictionary> CreateDictionary(Node root) { temp = stack.Pop(); - if (temp.Key.Count() == 1) + if (temp.IsLeaf) dictionary.Add(temp.Key[0], temp.BitString); else { if (temp.LeftChild != null) { - temp.LeftChild.BitString.AddRange(temp.BitString); - temp.LeftChild.BitString.Add(false); + temp.LeftChild.BitString += temp.BitString; + temp.LeftChild.BitString += 0; stack.Push(temp.LeftChild); } if (temp.RightChild != null) { - temp.RightChild.BitString.AddRange(temp.BitString); - temp.RightChild.BitString.Add(true); + temp.RightChild.BitString += temp.BitString; + temp.RightChild.BitString += 1; stack.Push(temp.RightChild); } } @@ -169,11 +170,12 @@ private static Dictionary> CreateDictionary(Node root) return dictionary; } - private static List CreateBitString(string input, Dictionary> dictionary) + private static string CreateBitString(string input, Dictionary dictionary) { - var bitString = new List(); + // We're using a string right here. While no compression is achieved with a string, it's the easiest way to display what the compressed result looks like. Also this is just an educational example. + var bitString = ""; foreach (var character in input) - bitString.AddRange(dictionary[character]); + bitString += dictionary[character]; return bitString; } diff --git a/chapters/data_compression/huffman/code/cs/Program.cs b/chapters/data_compression/huffman/code/cs/Program.cs index 09cc23dcb..5d92a211d 100644 --- a/chapters/data_compression/huffman/code/cs/Program.cs +++ b/chapters/data_compression/huffman/code/cs/Program.cs @@ -9,29 +9,14 @@ class Program static void Main(string[] args) { var result = HuffmanCoding.Encode("aaaabbbccd"); + // The bitStrings are just strings and provide no compression. Look in HuffmanCoding.cs for explanation. // Print dictionary. foreach (var entry in result.Dictionary) { - var bitString = ""; - foreach (var value in entry.Value) - { - if (value) - bitString += "1"; - else - bitString += "0"; - } - System.Console.WriteLine(entry.Key + " " + bitString); + System.Console.WriteLine($"{entry.Key} {entry.Value}"); } - // Print bitString. - var readableBitString = ""; - foreach (var boolean in result.BitString) - { - if (boolean) - readableBitString += "1"; - else - readableBitString += "0"; - } - System.Console.WriteLine($"{readableBitString} count: {readableBitString.Length}"); + // Print BitString. + System.Console.WriteLine($"{result.BitString} count: {result.BitString.Length}"); var originalString = HuffmanCoding.Decode(result); System.Console.WriteLine(originalString); From 233962f0a81a7655f47610b9af3c12fbc1238bf9 Mon Sep 17 00:00:00 2001 From: Julian Schacher Date: Tue, 29 May 2018 19:20:12 +0200 Subject: [PATCH 5/7] Make dictionary creation recursive. --- .../huffman/code/cs/HuffmanCoding.cs | 35 ++++++------------- 1 file changed, 11 insertions(+), 24 deletions(-) diff --git a/chapters/data_compression/huffman/code/cs/HuffmanCoding.cs b/chapters/data_compression/huffman/code/cs/HuffmanCoding.cs index 3b142a1d7..c6bb4b1ef 100644 --- a/chapters/data_compression/huffman/code/cs/HuffmanCoding.cs +++ b/chapters/data_compression/huffman/code/cs/HuffmanCoding.cs @@ -139,37 +139,24 @@ private static Dictionary CreateDictionary(Node root) { // We're using a string instead of a actual bits here, since it makes the code somewhat more readable and this is an educational example. var dictionary = new Dictionary(); + CreateDictionary(root, "", dictionary); + return dictionary; - var stack = new Stack(); - stack.Push(root); - Node temp; - - while (stack.Count != 0) + void CreateDictionary(Node node, string bitString, Dictionary localDictionary) { - temp = stack.Pop(); - - if (temp.IsLeaf) - dictionary.Add(temp.Key[0], temp.BitString); + if (node.IsLeaf) + localDictionary.Add(node.Key[0], bitString); else { - if (temp.LeftChild != null) - { - temp.LeftChild.BitString += temp.BitString; - temp.LeftChild.BitString += 0; - stack.Push(temp.LeftChild); - } - if (temp.RightChild != null) - { - temp.RightChild.BitString += temp.BitString; - temp.RightChild.BitString += 1; - stack.Push(temp.RightChild); - } + if (node.LeftChild != null) + CreateDictionary(node.LeftChild, bitString + '0', localDictionary); + if (node.RightChild != null) + CreateDictionary(node.RightChild, bitString + '1', localDictionary); } - } - - return dictionary; + } } + private static string CreateBitString(string input, Dictionary dictionary) { // We're using a string right here. While no compression is achieved with a string, it's the easiest way to display what the compressed result looks like. Also this is just an educational example. From ff95d099b60b28b85e9a49338a84e896b3e39ca1 Mon Sep 17 00:00:00 2001 From: Julian Schacher Date: Tue, 29 May 2018 21:33:35 +0200 Subject: [PATCH 6/7] Make HuffmanCoding non-static. Fix Add method. Change input to "bibbity bobbity". Remove unnecessary braces. --- .../huffman/code/cs/HuffmanCoding.cs | 24 +++++++++---------- .../huffman/code/cs/Program.cs | 8 +++---- 2 files changed, 15 insertions(+), 17 deletions(-) diff --git a/chapters/data_compression/huffman/code/cs/HuffmanCoding.cs b/chapters/data_compression/huffman/code/cs/HuffmanCoding.cs index c6bb4b1ef..a05c04d44 100644 --- a/chapters/data_compression/huffman/code/cs/HuffmanCoding.cs +++ b/chapters/data_compression/huffman/code/cs/HuffmanCoding.cs @@ -19,7 +19,7 @@ public EncodingResult(string bitString, Dictionary dictionary, Huf } } - public static class HuffmanCoding + public class HuffmanCoding { // The Node class used for the Huffman Tree. public class Node : IComparable @@ -63,13 +63,11 @@ public NodePriorityList(List givenNodes) public void Add(Node newNode) { - var index = ~this.nodes.BinarySearch(newNode); - if (index == this.nodes.Count) - { - this.nodes.Add(newNode); - return; - } - this.nodes.Insert(~index, newNode); + var index = this.nodes.BinarySearch(newNode); + if (index < 0) + this.nodes.Insert(~index, newNode); + else + this.nodes.Insert(index, newNode); } public Node Pop() @@ -80,7 +78,7 @@ public Node Pop() } } - public static EncodingResult Encode(string input) + public EncodingResult Encode(string input) { var root = CreateTree(input); var dictionary = CreateDictionary(root); @@ -89,7 +87,7 @@ public static EncodingResult Encode(string input) return new EncodingResult(bitString, dictionary, root); } - public static string Decode(EncodingResult result) + public string Decode(EncodingResult result) { var output = ""; Node currentNode = result.Tree; @@ -110,7 +108,7 @@ public static string Decode(EncodingResult result) return output; } - private static Node CreateTree(string input) + private Node CreateTree(string input) { // Create a List of all characters and their count in input by putting them into nodes. var nodes = input @@ -135,7 +133,7 @@ private static Node CreateTree(string input) return nodePriorityList.Pop(); } - private static Dictionary CreateDictionary(Node root) + private Dictionary CreateDictionary(Node root) { // We're using a string instead of a actual bits here, since it makes the code somewhat more readable and this is an educational example. var dictionary = new Dictionary(); @@ -157,7 +155,7 @@ void CreateDictionary(Node node, string bitString, Dictionary loca } - private static string CreateBitString(string input, Dictionary dictionary) + private string CreateBitString(string input, Dictionary dictionary) { // We're using a string right here. While no compression is achieved with a string, it's the easiest way to display what the compressed result looks like. Also this is just an educational example. var bitString = ""; diff --git a/chapters/data_compression/huffman/code/cs/Program.cs b/chapters/data_compression/huffman/code/cs/Program.cs index 5d92a211d..43a12b881 100644 --- a/chapters/data_compression/huffman/code/cs/Program.cs +++ b/chapters/data_compression/huffman/code/cs/Program.cs @@ -8,17 +8,17 @@ class Program { static void Main(string[] args) { - var result = HuffmanCoding.Encode("aaaabbbccd"); + var huffmanCoding = new HuffmanCoding(); + + var result = huffmanCoding.Encode("bibbity bobbity"); // The bitStrings are just strings and provide no compression. Look in HuffmanCoding.cs for explanation. // Print dictionary. foreach (var entry in result.Dictionary) - { System.Console.WriteLine($"{entry.Key} {entry.Value}"); - } // Print BitString. System.Console.WriteLine($"{result.BitString} count: {result.BitString.Length}"); - var originalString = HuffmanCoding.Decode(result); + var originalString = huffmanCoding.Decode(result); System.Console.WriteLine(originalString); } } From 2f79bb51b5b86516c315453fd37e464370099729 Mon Sep 17 00:00:00 2001 From: Julian Schacher Date: Tue, 29 May 2018 23:49:50 +0200 Subject: [PATCH 7/7] Use new mention template. --- chapters/data_compression/huffman/code/cs/HuffmanCoding.cs | 2 +- chapters/data_compression/huffman/code/cs/Program.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/chapters/data_compression/huffman/code/cs/HuffmanCoding.cs b/chapters/data_compression/huffman/code/cs/HuffmanCoding.cs index a05c04d44..49ace6fde 100644 --- a/chapters/data_compression/huffman/code/cs/HuffmanCoding.cs +++ b/chapters/data_compression/huffman/code/cs/HuffmanCoding.cs @@ -1,4 +1,4 @@ -// submitted by Julian Schacher (jspp) with help by gustorn. +// submitted by Julian Schacher (jspp), thanks to gustorn for the help using System; using System.Collections.Generic; using System.Linq; diff --git a/chapters/data_compression/huffman/code/cs/Program.cs b/chapters/data_compression/huffman/code/cs/Program.cs index 43a12b881..a336507ad 100644 --- a/chapters/data_compression/huffman/code/cs/Program.cs +++ b/chapters/data_compression/huffman/code/cs/Program.cs @@ -1,4 +1,4 @@ -// submitted by Julian Schacher (jspp) with help by gustorn. +// submitted by Julian Schacher (jspp), thanks to gustorn for the help using System.Collections; using System.Collections.Generic;