哈夫曼编码C#版做的改进,可用于简单加密
就是把01010的数据换成了可以自定义的字典.如果字典数量比字符数量多,就会把多出来的字典去掉。
如果字典里值有重复的话,也会把重复值去掉。
其实就是把左右子树变成数组,但其他对二叉树的操作就会受影响了。
==========================================================================
具体代码如下
class Program { static void Main(string[] args) { string source = "哈弗曼曼曼曼曼"; Huffman hf = new Huffman("qwer".ToCharArray()); Dictionary<char, string> key = null; var hfCode = hf.StringToHuffmanCode(out key, source); Console.WriteLine("编码与解析"); Console.WriteLine("编码: "+hfCode); var text = hf.ToText(hfCode, key); Console.WriteLine("解析: " + text); Console.ReadLine(); } }
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace ConsoleApplication1 { public class Huffman { public class Node : IComparable { public Node[] Child { get; set; } public int Weight { get; set; } public char Key { get; set; } public Node() { } public Node(int weight, char value) { this.Weight = weight; this.Key = value; } public int CompareTo(object obj) { int result = 0; Node tmp = obj as Node; if (tmp.Weight > this.Weight) { result = 1; } else if (tmp.Weight < this.Weight) { result = -1; } return result; } } private char[] mDict; private char[] mCntDict; public Huffman(char[] dict) { this.mDict = dict.Distinct().ToArray(); mCntDict = mDict; } public Node[] GetWeightArray(string str) { List<Node> result = new List<Node>(); char[] charArr = str.ToCharArray(); if (charArr.Length < mDict.Length) { char[] tmp = new char[charArr.Length]; Array.Copy(mDict, 0, tmp, 0, charArr.Length); mCntDict = tmp; } while (charArr.Length > 0) { char[] cntChars = null; var tmp = charArr.Where(m => m == charArr[0]); cntChars = new char[tmp.Count()]; tmp.ToArray().CopyTo(cntChars, 0); charArr = charArr.Where(m => m != tmp.First()).ToArray(); result.Add(new Node(cntChars.Length, cntChars[0])); } return result.ToArray(); } /// <summary> /// 两个一放变成N个一放 /// </summary> public Node CreateHuffmanTree(Node[] sources) { Node result = null; Node[] nodes = sources; while (true) { if (nodes.Length <= mCntDict.Length) { result = new Node(); result.Child = nodes; break; } Array.Sort(nodes); Node tmp = new Node(); tmp.Child = new Node[mCntDict.Length]; for (int i = nodes.Length - 1, j=0; i >= 0; i--, j++) { if (j < mCntDict.Length) { tmp.Weight += nodes[i].Weight; tmp.Child[j] = nodes[i]; } else { break; } } Node[] tmpNds = new Node[nodes.Length - (mCntDict.Length-1)]; Array.Copy(nodes, 0, tmpNds, 0, nodes.Length - (mCntDict.Length - 1)); tmpNds[tmpNds.Length - 1] = tmp; nodes = tmpNds; } return result; } public string StringToHuffmanCode(out Dictionary<char, string> key, string str) { string result = ""; var tmps = GetWeightArray(str); var tree = CreateHuffmanTree(tmps); var dict = CreateHuffmanCode(tree); foreach (var item in dict) { Console.WriteLine(item); } result = ToHuffmanCode(str, dict); key = dict; return result; } public Dictionary<char, string> CreateHuffmanCode(Node hTree) { return CreateHuffmanCode("", hTree); } private Dictionary<char, string> CreateHuffmanCode(string code, Node hTree) { Dictionary<char, string> result = new Dictionary<char, string>(); if (hTree.Child == null) { result.Add(hTree.Key, code); } else { for (int i = 0; i < hTree.Child.Length; i++) { var tmpDict = CreateHuffmanCode(code+mCntDict[i], hTree.Child[i]); foreach (var item in tmpDict) { result.Add(item.Key, item.Value); } } } return result; } public string ToHuffmanCode(string source, Dictionary<char, string> hfdict) { string result = ""; for (int i = 0; i < source.Length; i++) { result += hfdict.First(m => m.Key == source[i]).Value; } return result; } public string ToText(string code, Dictionary<char, string> hfdict) { string result = ""; for (int i = 0; i < code.Length; ) { foreach (var item in hfdict) { if ( code[i] == item.Value[0] && item.Value.Length + i <= code.Length) { char[] tmpArr = new char[item.Value.Length]; Array.Copy(code.ToCharArray(), i, tmpArr, 0, tmpArr.Length); if (new String(tmpArr) == item.Value) { result += item.Key; i += item.Value.Length; break; } } } } return result; } } }