哈弗曼编码算法(简单链表法)
2011-12-26 23:24 java线程例子 阅读(221) 评论(0) 收藏 举报算法代码如下:
public class HuffmanNode
{
public char Char { get; set; }
public int Frequency { get; set; }
//用于构造哈弗曼树
internal HuffmanNode LeftChild { get; set; }
internal HuffmanNode RightChild { get; set; }
//用于构造链表
internal HuffmanNode NextSibling { get; set; }
public string HuffmanCode {get;set;}
public HuffmanNode(char Char,int Freq)
{
this.Char = Char;
this.Frequency = Freq;
}
}
public class HuffmanAlgorithms
{
/// <summary>
/// 进行哈弗曼编码,编码过程中不改变Nodes节点,仅改变一些域。
/// </summary>
/// <param name="Nodes"></param>
public static void HuffmanCode(HuffmanNode[] Nodes)
{
if (Nodes == null || Nodes.Length == 0)
{
return;
}
#region 这个处理可以不要
if (Nodes.Length == 1)
{
Nodes[0].HuffmanCode = "0";
return;
}
if (Nodes.Length == 2)
{
Nodes[0].HuffmanCode = "0";
Nodes[1].HuffmanCode = "1";
return;
}
#endregion
HuffmanNode theHead = null;
//用插入排序算法,建立升序节点链表O(n^2)
for (int i = 0; i < Nodes.Length;i++ )
{
InsertNode(ref theHead, Nodes[i]);
}
//建立Huffman树,采用贪婪法,每次取链表中最小的两个(前两个).
HuffmanNode theTmp1 = null;
HuffmanNode theTmp2 = null;
theTmp1 = theHead;
if (theHead != null)
{
theTmp2 = theHead.NextSibling;
}
//链表里有两个则操作,则继续建树,否则树建立完成,退出循环.O(n*lgn)
while (theTmp1 != null && theTmp2 != null)
{
//建立一个内节点包含当前链表中两个最小元素,这个节点的频率是这两个元素的频率之和.
HuffmanNode theParent = new HuffmanNode('\0', theTmp1.Frequency + theTmp2.Frequency);
theParent.LeftChild = theTmp1;
theParent.RightChild = theTmp2;
//除掉当前两个最小元素,并插入新建节点.
theHead = theTmp2.NextSibling;
//将新建立的内节点插入当前链表.
InsertNode(ref theHead, theParent);
theTmp1 = theHead;
if (theHead != null)
{
theTmp2 = theHead.NextSibling;
}
}
//采用树的先序遍历进行编码.结果存放在节点的编码域中.o(n)
HuffmanCode(theHead, "");
//清理临时域,保证内存释放.o(n)
foreach (var node in Nodes)
{
node.LeftChild = null;
node.NextSibling = null;
node.RightChild = null;
}
}
/// <summary>
/// 利用树的先序遍历进行编码,实际上有效的都是叶子节点,叶子节点都在Nodes数组中。
/// </summary>
/// <param name="ANode"></param>
/// <param name="StrCode"></param>
private static void HuffmanCode(HuffmanNode ANode, string StrCode)
{
if (ANode != null)
{
ANode.HuffmanCode = StrCode;
if (ANode.LeftChild != null)
{
HuffmanCode(ANode.LeftChild, StrCode + "0");
}
if (ANode.RightChild != null)
{
HuffmanCode(ANode.RightChild, StrCode + "1");
}
}
}
/// <summary>
/// 将节点Node插入到链表AHead中去,并升序排列.
/// </summary>
/// <param name="AHead"></param>
/// <param name="Node"></param>
private static void InsertNode(ref HuffmanNode AHead,HuffmanNode Node)
{
HuffmanNode theTmp1 = AHead;
HuffmanNode theTmp2 = null;
while (theTmp1 != null && theTmp1.Frequency < Node.Frequency)
{
theTmp2 = theTmp1;
theTmp1 = theTmp1.NextSibling;
}
if (theTmp2 == null)
{
AHead = Node;
}
else
{
theTmp2.NextSibling = Node;
}
Node.NextSibling = theTmp1;
}
}
PS:这个算法利用最小堆效率要高些,在O(nlgn),这里的算法还是O(n^2),符合插入排序算法的时间复杂度.
浙公网安备 33010602011771号