实现思想:
1.首先分析输入的报文,得到各个字符出现的次数和概率,将出现次数作为权重构建哈夫曼树
2.构造huffman树,并动态显示Huffman树的生成过程
3,对每个字符进行编码
4.对字符串编译码
5,Socket编程实现通信(重点学习)
界面:
关键代码:
1.
enum { IDD = IDD_HUFFMAN_DIALOG };
CListCtrl m_plist;
CString m_mes;
——————————————————
m_plist.InsertColumn( 0, "字符", LVCFMT_LEFT, 40 );//插入列
m_plist.InsertColumn( 1, "次数", LVCFMT_CENTER, 40 );//插入列
m_plist.InsertColumn( 2, "概率", LVCFMT_CENTER, 60 );//插入列
m_plist.InsertColumn( 3, "hfm编码", LVCFMT_CENTER, 100 );//插入列
————————————————————
int CHuffmanDlg::Probability(CString str)//统计每个字符出现概率,返回不同字符个数
{
CString pro;//存储字符概率
if (str==""){MessageBox("输入报文为空!"); return 0;}
int StrLength=str.GetLength();//字符串总长
int i=0,j=0;
CString temp;
while (str!="")
{
temp.Format(_T("%c"), str[0]);;
m_plist.InsertItem(i,temp);//字符
j=str.Remove(str[0]);
temp.Format(_T("%d"),j);//字符出现次数
m_plist.SetItemText(i,1,temp);
temp.Format(_T("%3f"),(double)j/StrLength);
m_plist.SetItemText(i,2,temp);//字符出现概率
i++;
}
return i;
2.huffman树和节点的数据结构定义
typedef struct HuffmanNode
{
int weight;//权值
char character;//存放字符
bool isLeaf;//是否叶子节点
int createSort; //用于标记节点创建顺序
int position; //用于记录节点在树中的位置。以完全二叉树计算的
HuffmanNode *leftChild,*rightChild,*parent;//三叉链表指针
HuffmanNode():leftChild(NULL),rightChild(NULL),parent(NULL){}
HuffmanNode(int elem,char ch,HuffmanNode* left = NULL, HuffmanNode* right = NULL, HuffmanNode* ptr = NULL ):weight(elem),character(ch),
leftChild(left), rightChild(right), parent(ptr){}
bool operator <=(HuffmanNode& R){return weight <= R.weight;}
bool operator > (HuffmanNode& R){return weight > R.weight;}
HuffmanNode* sAddress;
int visited;//访问标记,编码时使用
CString hfmCode;
}HuffmanNode;
class HuffanTree
{
public:
int createSort;
void mergeTree(HuffmanNode & ht1, HuffmanNode & ht2, HuffmanNode*& parent);
void enCode(int n,CListCtrl *list); //对哈弗曼树进行编码 ,n个叶子节点
void CreateHfmTree(int n,CListCtrl * list);//创建哈弗曼树
HuffanTree();
virtual ~HuffanTree();
HuffmanNode *huffNode[256]; //申请编码空间,最多有256中不同字符
HuffmanNode* root;
int codeTotal; //编码节点的个数,即需要多少个huffmanNode
HuffmanNode* rootFull; //绘画时候需要的满二叉树
};
创建huffman树:
void HuffanTree::CreateHfmTree(int n,CListCtrl *list)
{
codeTotal = n; //总共需要n个节点,因为共出现了n个不重复的字符
createSort=1;
int i,elem;//elem为字符出现次数,置为权值
char ch;//字符
MinHeap hp(n);//初始化最小堆
CString str;
HuffmanNode *parent,first,second,*work;
for (i=0;i<codeTotal;i++)//构造n个叶子节点
{
elem=_ttoi(list->GetItemText(i,1));//CString转为int
ch= list->GetItemText(i,0)[0];
work = new HuffmanNode;
work->weight = elem;
work->character = ch;
work->position = i;
work->isLeaf = true;
work->visited=0;//叶子节点记录为未访问
work->leftChild = NULL;
work->rightChild = NULL;
work->parent = NULL;
work->sAddress = work;
hp.Insert(*work);
//huffNode[i]=work;
}
int leafNum=0;
for(i = 0; i < n-1; i++){
hp.RemoveMin(first);
hp.RemoveMin(second);
mergeTree(first,second,parent);
if (first.rightChild==NULL&&first.leftChild==NULL)
{
huffNode[leafNum++]=first.sAddress;
}
if (second.rightChild==NULL&&second.leftChild==NULL)//记录叶子节点
{
huffNode[leafNum++]=second.sAddress;
}
hp.Insert(*parent);
}
root = parent;
root->createSort = createSort;//最后创建
}
void HuffanTree::mergeTree(HuffmanNode &ht1, HuffmanNode &ht2, HuffmanNode* & parent)
{
parent = new HuffmanNode;
parent->leftChild = ht1.sAddress;
parent->rightChild = ht2.sAddress;
parent->weight = ht1.weight + ht2.weight;
parent->position = -1; //给父节点的位置赋-1,父节点不是要编码的节点
parent->character = '#'; //给父节点一个标志
parent->visited=1; //父节点标记为已访问
ht1.sAddress->parent = ht2.sAddress->parent = parent;
ht1.sAddress->createSort = createSort++;
ht2.sAddress->createSort = createSort++;
parent->isLeaf = false;
parent->sAddress=parent;
}