您的位置:首页 > 编程语言 > C#

C#实现Huffman编码和解码

2010-01-18 10:11 441 查看
关于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;
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: