- 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
- #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;
- }
- }
- }
C#实现Huffman编码和解码
最新推荐文章于 2024-06-14 09:51:31 发布
本文介绍了一种基于霍夫曼编码的字符串压缩方法,并详细展示了如何构建霍夫曼树及编码过程。通过霍夫曼树可以为不同字符分配长度不一的编码,从而实现高效的数据压缩。

1万+

被折叠的 条评论
为什么被折叠?



