C#实现Huffman编码和解码

本文介绍了一种基于霍夫曼编码的字符串压缩方法,并详细展示了如何构建霍夫曼树及编码过程。通过霍夫曼树可以为不同字符分配长度不一的编码,从而实现高效的数据压缩。
 
  1. using System;
  2. using System.Collections;
  3. using System.Collections.Generic;
  4. using System.Linq;
  5. using System.Text;
  6. namespace StringCompresser
  7. {
  8.     public class Huffman
  9.     {
  10.         //char and its bitarray
  11.         public Dictionary<char, BitArray> HuffmanCode = null;
  12.         //Huffman tree
  13.         public Node[] HuffmanTree = null;
  14.         //huffman tree node
  15.         internal struct Node
  16.         {
  17.             internal char character;
  18.             internal int weight;
  19.             internal int parent;
  20.             internal int lchild;
  21.             internal int rchild;
  22.         }
  23.         public Huffman(char[] charArray, int[] weight)
  24.         {
  25.             if (weight == null || weight.Length == 0 
  26.                 || charArray == null || charArray.Length == 0
  27.                 || weight.Length != charArray.Length)
  28.                 return;
  29.             HuffmanCode = new Dictionary<char, BitArray>();
  30.             //build huffman tree
  31.             int totalNodeNum = weight.Length * 2 - 1;
  32.             HuffmanTree = new Node[totalNodeNum + 1];
  33.             //initialize the first weight.Length nodes with wight.
  34.             //The 0 element is reserved for other purpose
  35.             for(int i = 0; i < weight.Length; i++)
  36.             {
  37.                 HuffmanTree[i + 1] = new Node { 
  38.                                                 weight = weight[i], 
  39.                                                 parent = 0, 
  40.                                                 lchild = 0, 
  41.                                                 rchild = 0, 
  42.                                                 character= charArray[i] 
  43.                                               };
  44.             }
  45.             for (int i = weight.Length + 1; i < HuffmanTree.Length; i++)
  46.             {
  47.                 //select two min weight from huffmanTree.parent is 0
  48.                 #region selection
  49.                 int? min1 = null;
  50.                 int? min2 = null;
  51.                 int min1Pos = 0;
  52.                 int min2Pos = 0;
  53.                 for (int j = 1; j < i; j++)
  54.                 {
  55.                     if (HuffmanTree[j].parent == 0)
  56.                     {
  57.                         if (min1 == null)
  58.                         {
  59.                             min1 = HuffmanTree[j].weight;
  60.                             min1Pos = j;
  61.                             continue;
  62.                         }
  63.                         if (min2 == null)
  64.                         {
  65.                             if (HuffmanTree[j].weight < min1.Value)
  66.                             {
  67.                                 min2 = min1;
  68.                                 min2Pos = min1Pos;
  69.                                 min1 = HuffmanTree[j].weight;
  70.                                 min1Pos = j;
  71.                             }
  72.                             else
  73.                             {
  74.                                 min2 = HuffmanTree[j].weight;
  75.                                 min2Pos = j;
  76.                             }
  77.                             continue;
  78.                         }
  79.                         if(min1 != null && min2 != null)
  80.                         {
  81.                             if (HuffmanTree[j].weight < min1)
  82.                             {
  83.                                 min2 = min1;
  84.                                 min2Pos = min1Pos;
  85.                                 min1 = HuffmanTree[j].weight;
  86.                                 min1Pos = j;
  87.                             }
  88.                             else if (HuffmanTree[j].weight < min2)
  89.                             {
  90.                                 min2 = HuffmanTree[j].weight;
  91.                                 min2Pos = j;
  92.                             }
  93.                         }
  94.                     }
  95.                 }
  96.                 #endregion
  97.                 HuffmanTree[min1Pos].parent = HuffmanTree[min2Pos].parent = i;
  98.                 HuffmanTree[i].lchild = min1Pos;
  99.                 HuffmanTree[i].rchild = min2Pos;
  100.                 HuffmanTree[i].weight = min1.Value + min2.Value;                
  101.             }
  102.             //Get huffman code
  103.             
  104.             int p = 0,c =0;
  105.             List<bool> values = null;
  106.             for (int i = 1; i <= weight.Length; i++)
  107.             {
  108.                 values = new List<bool>();
  109.                 
  110.                 //one points to _current node, one point to _parent node
  111.                 for (c = i, p = HuffmanTree[c].parent; p != 0; c = p, p = HuffmanTree[p].parent)
  112.                 {
  113.                     if (HuffmanTree[p].lchild == c)//0
  114.                     {
  115.                         values.Add(false);
  116.                     }
  117.                     else//1
  118.                     {
  119.                         values.Add(true);
  120.                     }
  121.                 }
  122.                 values.Reverse();
  123.                 HuffmanCode.Add(charArray[i - 1], new BitArray(values.ToArray()));
  124.             }            
  125.         }
  126.         //Encode a string to bitarray
  127.         public BitArray Encode(string input)
  128.         {
  129.             if (string.IsNullOrEmpty(input))
  130.                 return null;
  131.             List<bool> list = new List<bool>();
  132.             foreach (char ch in input)
  133.             {
  134.                 BitArray ba = HuffmanCode[ch];
  135.                 foreach (bool b in ba)
  136.                 {
  137.                     list.Add(b);
  138.                 }
  139.             }
  140.             return new BitArray(list.ToArray());
  141.         }
  142.         //Decode a bitarray to a string
  143.         public string Decode(BitArray bitArray)
  144.         {
  145.             if (bitArray == null)
  146.                 return null;
  147.             string rtnString = string.Empty;
  148.             int ic = HuffmanTree.Length - 1;//Root
  149.             Node current = HuffmanTree[ic];
  150.             int i = 0;
  151.             while (i <= bitArray.Length - 1)
  152.             {
  153.                 while (current.lchild != 0 && current.rchild != 0)
  154.                 {
  155.                     current = bitArray[i++] ? HuffmanTree[current.rchild] : HuffmanTree[current.lchild];
  156.                 }
  157.                 rtnString = string.Concat(rtnString, current.character);
  158.                 current = HuffmanTree[ic];
  159.             }
  160.             return rtnString;
  161.         }
  162.         
  163.         //Get char from a char bitarray
  164.         private char GetCharacter(BitArray array)
  165.         {
  166.             int ic = HuffmanTree.Length - 1;//Root
  167.             Node c = HuffmanTree[ic];
  168.             
  169.             foreach (bool b in array)
  170.             {
  171.                 if (b)
  172.                 {
  173.                     ic = c.rchild;
  174.                 }
  175.                 else
  176.                 {
  177.                     ic = c.lchild;
  178.                 }
  179.                 c = HuffmanTree[ic];
  180.             }
  181.             return c.character;
  182.         }
  183.     }
  184. }
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值