A-M baby
This commit is contained in:
parent
764da6cbbb
commit
db842d013d
19005 changed files with 197040 additions and 7 deletions
314
Task/Huffman-coding/C-sharp/huffman-coding.cs
Normal file
314
Task/Huffman-coding/C-sharp/huffman-coding.cs
Normal file
|
|
@ -0,0 +1,314 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Huffman_Encoding
|
||||
{
|
||||
public class PriorityQueue<T> where T : IComparable
|
||||
{
|
||||
protected List<T> LstHeap = new List<T>();
|
||||
|
||||
public virtual int Count
|
||||
{
|
||||
get { return LstHeap.Count; }
|
||||
}
|
||||
|
||||
public virtual void Add(T val)
|
||||
{
|
||||
LstHeap.Add(val);
|
||||
SetAt(LstHeap.Count - 1, val);
|
||||
UpHeap(LstHeap.Count - 1);
|
||||
}
|
||||
|
||||
public virtual T Peek()
|
||||
{
|
||||
if (LstHeap.Count == 0)
|
||||
{
|
||||
throw new IndexOutOfRangeException("Peeking at an empty priority queue");
|
||||
}
|
||||
|
||||
return LstHeap[0];
|
||||
}
|
||||
|
||||
public virtual T Pop()
|
||||
{
|
||||
if (LstHeap.Count == 0)
|
||||
{
|
||||
throw new IndexOutOfRangeException("Popping an empty priority queue");
|
||||
}
|
||||
|
||||
T valRet = LstHeap[0];
|
||||
|
||||
SetAt(0, LstHeap[LstHeap.Count - 1]);
|
||||
LstHeap.RemoveAt(LstHeap.Count - 1);
|
||||
DownHeap(0);
|
||||
return valRet;
|
||||
}
|
||||
|
||||
protected virtual void SetAt(int i, T val)
|
||||
{
|
||||
LstHeap[i] = val;
|
||||
}
|
||||
|
||||
protected bool RightSonExists(int i)
|
||||
{
|
||||
return RightChildIndex(i) < LstHeap.Count;
|
||||
}
|
||||
|
||||
protected bool LeftSonExists(int i)
|
||||
{
|
||||
return LeftChildIndex(i) < LstHeap.Count;
|
||||
}
|
||||
|
||||
protected int ParentIndex(int i)
|
||||
{
|
||||
return (i - 1) / 2;
|
||||
}
|
||||
|
||||
protected int LeftChildIndex(int i)
|
||||
{
|
||||
return 2 * i + 1;
|
||||
}
|
||||
|
||||
protected int RightChildIndex(int i)
|
||||
{
|
||||
return 2 * (i + 1);
|
||||
}
|
||||
|
||||
protected T ArrayVal(int i)
|
||||
{
|
||||
return LstHeap[i];
|
||||
}
|
||||
|
||||
protected T Parent(int i)
|
||||
{
|
||||
return LstHeap[ParentIndex(i)];
|
||||
}
|
||||
|
||||
protected T Left(int i)
|
||||
{
|
||||
return LstHeap[LeftChildIndex(i)];
|
||||
}
|
||||
|
||||
protected T Right(int i)
|
||||
{
|
||||
return LstHeap[RightChildIndex(i)];
|
||||
}
|
||||
|
||||
protected void Swap(int i, int j)
|
||||
{
|
||||
T valHold = ArrayVal(i);
|
||||
SetAt(i, LstHeap[j]);
|
||||
SetAt(j, valHold);
|
||||
}
|
||||
|
||||
protected void UpHeap(int i)
|
||||
{
|
||||
while (i > 0 && ArrayVal(i).CompareTo(Parent(i)) > 0)
|
||||
{
|
||||
Swap(i, ParentIndex(i));
|
||||
i = ParentIndex(i);
|
||||
}
|
||||
}
|
||||
|
||||
protected void DownHeap(int i)
|
||||
{
|
||||
while (i >= 0)
|
||||
{
|
||||
int iContinue = -1;
|
||||
|
||||
if (RightSonExists(i) && Right(i).CompareTo(ArrayVal(i)) > 0)
|
||||
{
|
||||
iContinue = Left(i).CompareTo(Right(i)) < 0 ? RightChildIndex(i) : LeftChildIndex(i);
|
||||
}
|
||||
else if (LeftSonExists(i) && Left(i).CompareTo(ArrayVal(i)) > 0)
|
||||
{
|
||||
iContinue = LeftChildIndex(i);
|
||||
}
|
||||
|
||||
if (iContinue >= 0 && iContinue < LstHeap.Count)
|
||||
{
|
||||
Swap(i, iContinue);
|
||||
}
|
||||
|
||||
i = iContinue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal class HuffmanNode<T> : IComparable
|
||||
{
|
||||
internal HuffmanNode(double probability, T value)
|
||||
{
|
||||
Probability = probability;
|
||||
LeftSon = RightSon = Parent = null;
|
||||
Value = value;
|
||||
IsLeaf = true;
|
||||
}
|
||||
|
||||
internal HuffmanNode(HuffmanNode<T> leftSon, HuffmanNode<T> rightSon)
|
||||
{
|
||||
LeftSon = leftSon;
|
||||
RightSon = rightSon;
|
||||
Probability = leftSon.Probability + rightSon.Probability;
|
||||
leftSon.IsZero = true;
|
||||
rightSon.IsZero = false;
|
||||
leftSon.Parent = rightSon.Parent = this;
|
||||
IsLeaf = false;
|
||||
}
|
||||
|
||||
internal HuffmanNode<T> LeftSon { get; set; }
|
||||
internal HuffmanNode<T> RightSon { get; set; }
|
||||
internal HuffmanNode<T> Parent { get; set; }
|
||||
internal T Value { get; set; }
|
||||
internal bool IsLeaf { get; set; }
|
||||
|
||||
internal bool IsZero { get; set; }
|
||||
|
||||
internal int Bit
|
||||
{
|
||||
get { return IsZero ? 0 : 1; }
|
||||
}
|
||||
|
||||
internal bool IsRoot
|
||||
{
|
||||
get { return Parent == null; }
|
||||
}
|
||||
|
||||
internal double Probability { get; set; }
|
||||
|
||||
public int CompareTo(object obj)
|
||||
{
|
||||
return -Probability.CompareTo(((HuffmanNode<T>) obj).Probability);
|
||||
}
|
||||
}
|
||||
|
||||
public class Huffman<T> where T : IComparable
|
||||
{
|
||||
private readonly Dictionary<T, HuffmanNode<T>> _leafDictionary = new Dictionary<T, HuffmanNode<T>>();
|
||||
private readonly HuffmanNode<T> _root;
|
||||
|
||||
public Huffman(IEnumerable<T> values)
|
||||
{
|
||||
var counts = new Dictionary<T, int>();
|
||||
var priorityQueue = new PriorityQueue<HuffmanNode<T>>();
|
||||
int valueCount = 0;
|
||||
|
||||
foreach (T value in values)
|
||||
{
|
||||
if (!counts.ContainsKey(value))
|
||||
{
|
||||
counts[value] = 0;
|
||||
}
|
||||
counts[value]++;
|
||||
valueCount++;
|
||||
}
|
||||
|
||||
foreach (T value in counts.Keys)
|
||||
{
|
||||
var node = new HuffmanNode<T>((double) counts[value] / valueCount, value);
|
||||
priorityQueue.Add(node);
|
||||
_leafDictionary[value] = node;
|
||||
}
|
||||
|
||||
while (priorityQueue.Count > 1)
|
||||
{
|
||||
HuffmanNode<T> leftSon = priorityQueue.Pop();
|
||||
HuffmanNode<T> rightSon = priorityQueue.Pop();
|
||||
var parent = new HuffmanNode<T>(leftSon, rightSon);
|
||||
priorityQueue.Add(parent);
|
||||
}
|
||||
|
||||
_root = priorityQueue.Pop();
|
||||
_root.IsZero = false;
|
||||
}
|
||||
|
||||
public List<int> Encode(T value)
|
||||
{
|
||||
var returnValue = new List<int>();
|
||||
Encode(value, returnValue);
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
public void Encode(T value, List<int> encoding)
|
||||
{
|
||||
if (!_leafDictionary.ContainsKey(value))
|
||||
{
|
||||
throw new ArgumentException("Invalid value in Encode");
|
||||
}
|
||||
HuffmanNode<T> nodeCur = _leafDictionary[value];
|
||||
var reverseEncoding = new List<int>();
|
||||
while (!nodeCur.IsRoot)
|
||||
{
|
||||
reverseEncoding.Add(nodeCur.Bit);
|
||||
nodeCur = nodeCur.Parent;
|
||||
}
|
||||
|
||||
reverseEncoding.Reverse();
|
||||
encoding.AddRange(reverseEncoding);
|
||||
}
|
||||
|
||||
public List<int> Encode(IEnumerable<T> values)
|
||||
{
|
||||
var returnValue = new List<int>();
|
||||
|
||||
foreach (T value in values)
|
||||
{
|
||||
Encode(value, returnValue);
|
||||
}
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
public T Decode(List<int> bitString, ref int position)
|
||||
{
|
||||
HuffmanNode<T> nodeCur = _root;
|
||||
while (!nodeCur.IsLeaf)
|
||||
{
|
||||
if (position > bitString.Count)
|
||||
{
|
||||
throw new ArgumentException("Invalid bitstring in Decode");
|
||||
}
|
||||
nodeCur = bitString[position++] == 0 ? nodeCur.LeftSon : nodeCur.RightSon;
|
||||
}
|
||||
return nodeCur.Value;
|
||||
}
|
||||
|
||||
public List<T> Decode(List<int> bitString)
|
||||
{
|
||||
int position = 0;
|
||||
var returnValue = new List<T>();
|
||||
|
||||
while (position != bitString.Count)
|
||||
{
|
||||
returnValue.Add(Decode(bitString, ref position));
|
||||
}
|
||||
return returnValue;
|
||||
}
|
||||
}
|
||||
|
||||
internal class Program
|
||||
{
|
||||
private const string Example = "this is an example for huffman encoding";
|
||||
|
||||
private static void Main()
|
||||
{
|
||||
var huffman = new Huffman<char>(Example);
|
||||
List<int> encoding = huffman.Encode(Example);
|
||||
List<char> decoding = huffman.Decode(encoding);
|
||||
var outString = new string(decoding.ToArray());
|
||||
Console.WriteLine(outString == Example ? "Encoding/decoding worked" : "Encoding/Decoding failed");
|
||||
|
||||
var chars = new HashSet<char>(Example);
|
||||
foreach (char c in chars)
|
||||
{
|
||||
encoding = huffman.Encode(c);
|
||||
Console.Write("{0}: ", c);
|
||||
foreach (int bit in encoding)
|
||||
{
|
||||
Console.Write("{0}", bit);
|
||||
}
|
||||
Console.WriteLine();
|
||||
}
|
||||
Console.ReadKey();
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue