[问题描述]:设一份电文中有不同出现频率的字符,为了提高电文的输入和翻译效率,必须有一套简短而又不会产生歧义的字符代码。试根据哈夫曼算法,对电文中的不同字符,构造出一棵哈夫曼树,对每个字符进行编码。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using DS.BLL;
namespace HuffTree.CSharp
{
class Program
{
static void Main(string[] args)
{
int leafNum = 4;
int totalNodes = 2 * leafNum - 1;
int[] weight = new int[] { 3, 4, 1, 2 };
string[] alphabet = new string[] { "A", "B", "C", "D" };
//初始化
HuffmanTree[] huffmanTree = new HuffmanTree[totalNodes].Select(p => new HuffmanTree() { }).ToArray();
//构建
HuffmanTreeBLL.Create(huffmanTree, leafNum, weight);
//哈夫曼编码
string[] huffmanCode = HuffmanTreeBLL.Coding(huffmanTree, leafNum);
PrintResult(alphabet, huffmanTree, huffmanCode, leafNum);
Console.ReadKey();
}
private static void PrintResult(string[] alphabet, HuffmanTree[] huffmanTree, string[] huffmanCode, int leafNum)
{
if (alphabet.Count() < 1 || huffmanTree.Count() < 1 || huffmanCode.Count() < 1) return;
for (int i = 0; i < leafNum; i++)
{
Console.WriteLine("字符:{0},权重值:{1},哈夫曼编码:{2}", alphabet[i], huffmanTree[i].Weight, huffmanCode[i]);
}
}
}
}
namespace DS.BLL
{
///
public class HuffmanTreeBLL
{
public static HuffmanTree[] Create(HuffmanTree[] huffmanTree, int leafNum, int[] weight)
{
//获取哈夫曼树结点总数
int totalNodes = 2 * leafNum - 1;
InitLeafNode(huffmanTree, leafNum, weight);
//构造哈夫曼
for (int i = leafNum; i < totalNodes; i++)
{
//获取权重最小的两个叶子节点的下标
int minIndex1 = -1;
int minIndex2 = -1;
SelectNode(huffmanTree, i, ref minIndex1, ref minIndex2);
huffmanTree[minIndex1].Parent = i;
huffmanTree[minIndex2].Parent = i;
huffmanTree[i].Left = minIndex1;
huffmanTree[i].Right = minIndex2;
huffmanTree[i].Weight = huffmanTree[minIndex1].Weight + huffmanTree[minIndex2].Weight;
}
return huffmanTree;
}
public static string[] Coding(HuffmanTree[] huffmanTree, int leafNum)
{
string[] huffmanCode = new string[leafNum];
//当前节点下标
int current = 0;
//父节点下标
int parent = 0;
for (int i = 0; i < leafNum; i++)
{
string codeTemp = string.Empty;
current = i;
//第一次获取最左节点
parent = huffmanTree[current].Parent;
while (parent != 0)
{
if (huffmanTree[parent].Left == current) codeTemp += "0";
else codeTemp += "1";
current = parent;
parent = huffmanTree[parent].Parent;
}
huffmanCode[i] = new string(codeTemp.Reverse().ToArray());
}
return huffmanCode;
}
private static void InitLeafNode(HuffmanTree[] huffmanTree, int leafNum, int[] weight)
{
if (huffmanTree == null || leafNum < 1 || weight.Count() < 1) return;
for (int i = 0; i < leafNum; i++)
{
huffmanTree[i].Weight = weight[i];
}
}
private static void SelectNode(HuffmanTree[] huffmanTree, int searchNode, ref int minIndex1, ref int minIndex2)
{
HuffmanTree minNode1 = null;
HuffmanTree minNode2 = null;
for (int i = 0; i < searchNode; i++)
{
if (huffmanTree[i].Parent == 0)
{
//如果为null,则表示当前节叶子节点最小
if (minNode1 == null)
{
minIndex1 = i;
minNode1 = huffmanTree[i];
continue;
}
if (minNode2 == null)
{
minIndex2 = i;
minNode2 = huffmanTree[i];
//交换位置,确保minIndex1为最小
if (minNode1.Weight >= minNode2.Weight)
{
//节点交换
var temp = minNode1;
minNode1 = minNode2;
minNode2 = temp;
//交换下标
var tempIndex = minIndex1;
minIndex1 = minIndex2;
minIndex2 = tempIndex;
continue;
}
}
if (minNode1 != null && minNode2 != null)
{
if (huffmanTree[i].Weight < minNode1.Weight)
{
//将min1临时转存给min2
minNode2 = minNode1;
minNode1 = huffmanTree[i];
//记录在数组中的下标
minIndex2 = minIndex1;
minIndex1 = i;
}
else
{
if (huffmanTree[i].Weight < minNode2.Weight)
{
minNode2 = huffmanTree[i];
minIndex2 = i;
}
}
}
}
}
}
}
public class HuffmanTree
{
public int Weight { get; set; } //权值
public int Parent { get; set; } //父节点
public int Left { get; set; } //左孩子节点
public int Right { get; set; } //右孩子节点
}
}
说点什么
欢迎讨论