C#实现Huffman编码和解码

关于Huffman概念,参见数据结构书

using System; 

using System.Collections; 

using System.Collections.Generic; 

using System.Linq; 

using System.Text; 



namespace StringCompresser 

{ 



    public class Huffman 

    { 

        //char and its bitarray 

        public Dictionary<char, BitArray> HuffmanCode = null; 



        //Huffman tree 

        public Node[] HuffmanTree = null; 



        //huffman tree node 

        internal struct Node 

        { 

            internal char character; 

            internal int weight; 

            internal int parent; 

            internal int lchild; 

            internal int rchild; 

        } 



        public Huffman(char[] charArray, int[] weight) 

        { 

            if (weight == null || weight.Length == 0  

                || charArray == null || charArray.Length == 0 

                || weight.Length != charArray.Length) 

                return; 



            HuffmanCode = new Dictionary<char, BitArray>(); 



            //build huffman tree 



            int totalNodeNum = weight.Length * 2 - 1; 



            HuffmanTree = new Node[totalNodeNum + 1]; 



            //initialize the first weight.Length nodes with wight. 

            //The 0 element is reserved for other purpose 

            for(int i = 0; i < weight.Length; i++) 

            { 

                HuffmanTree[i + 1] = new Node {  

                                                weight = weight[i],  

                                                parent = 0,  

                                                lchild = 0,  

                                                rchild = 0,  

                                                character= charArray[i]  

                                              }; 

            } 



            for (int i = weight.Length + 1; i < HuffmanTree.Length; i++) 

            { 

                //select two min weight from huffmanTree.parent is 0
//This Algorithm only traverse array once
#region selection int? min1 = null; int? min2 = null; int min1Pos = 0; int min2Pos = 0; for (int j = 1; j < i; j++) { if (HuffmanTree[j].parent == 0) { if (min1 == null) { min1 = HuffmanTree[j].weight; min1Pos = j; continue; } if (min2 == null) { if (HuffmanTree[j].weight < min1.Value) { min2 = min1; min2Pos = min1Pos; min1 = HuffmanTree[j].weight; min1Pos = j; } else { min2 = HuffmanTree[j].weight; min2Pos = j; } continue; } if(min1 != null && min2 != null) { if (HuffmanTree[j].weight < min1) { min2 = min1; min2Pos = min1Pos; min1 = HuffmanTree[j].weight; min1Pos = j; } else if (HuffmanTree[j].weight < min2) { min2 = HuffmanTree[j].weight; min2Pos = j; } } } } #endregion HuffmanTree[min1Pos].parent = HuffmanTree[min2Pos].parent = i; HuffmanTree[i].lchild = min1Pos; HuffmanTree[i].rchild = min2Pos; HuffmanTree[i].weight = min1.Value + min2.Value; } //Get huffman code int p = 0,c =0; List<bool> values = null; for (int i = 1; i <= weight.Length; i++) { values = new List<bool>(); //one points to _current node, one point to _parent node for (c = i, p = HuffmanTree[c].parent; p != 0; c = p, p = HuffmanTree[p].parent) { if (HuffmanTree[p].lchild == c)//0 { values.Add(false); } else//1 { values.Add(true); } } values.Reverse(); HuffmanCode.Add(charArray[i - 1], new BitArray(values.ToArray())); } } //Encode a string to bitarray public BitArray Encode(string input) { if (string.IsNullOrEmpty(input)) return null; List<bool> list = new List<bool>(); foreach (char ch in input) { BitArray ba = HuffmanCode[ch]; foreach (bool b in ba) { list.Add(b); } } return new BitArray(list.ToArray()); } //Decode a bitarray to a string public string Decode(BitArray bitArray) { if (bitArray == null) return null; string rtnString = string.Empty; int ic = HuffmanTree.Length - 1;//Root Node current = HuffmanTree[ic]; int i = 0; while (i <= bitArray.Length - 1) { while (current.lchild != 0 && current.rchild != 0) { current = bitArray[i++] ? HuffmanTree[current.rchild] : HuffmanTree[current.lchild]; } rtnString = string.Concat(rtnString, current.character); current = HuffmanTree[ic]; } return rtnString; } //Get char from a char bitarray private char GetCharacter(BitArray array) { int ic = HuffmanTree.Length - 1;//Root Node c = HuffmanTree[ic]; foreach (bool b in array) { if (b) { ic = c.rchild; } else { ic = c.lchild; } c = HuffmanTree[ic]; } return c.character; } } }

你可能感兴趣的:(Huffman)