// Huffman.cpp : Defines the entry point for the console application.
/*-----CODE FOR FUN---------------
-------CREATED BY Dream_Whui------
-------2015-2-8-------------------*/
#include "stdafx.h"
#include <iostream>
using namespace std;
typedef struct//定义哈弗曼树的结构
{
unsigned int weight;//权重
unsigned int parent, lchild, rchild;//双亲结点,做孩子,右孩子
}HTNode, *HuffmanTree;
typedef char** HuffmanCode;
void Select(HuffmanTree HT, int n, int &s1, int &s2)//选出哈弗曼树HT中权值最小,双亲结点序号为0,的两个结点,序号赋值给s1,s2
{
int i,f1,f2;
unsigned int k = UINT_MAX;
for(i=1; i<=n; i++)//找到权值最小的结点
{
if(HT[i].parent == 0)
if(HT[i].weight < k)
{
k = HT[i].weight;
f1 = i;
}
}
HT[f1].parent = 1;//双亲结点设为1,做为标记(不会再被选到)
s1 = f1;
k = UINT_MAX;
for(i=1; i<=n; i++)//找到权值第二小的结点
{
if(HT[i].parent == 0)
if(HT[i].weight < k)
{
k = HT[i].weight;
f2 = i;
}
}
HT[f2].parent = 1;
s2 = f2;
int temp;
if(s1>s2)
{
temp = s1;
s1 = s2;
s2 = temp;
}
}
void HuffmanCoding(HuffmanTree &HT, HuffmanCode &HC, int *w, int n)
{ //构造哈弗曼树HT,哈弗曼树编码HC,w为结点的权重值,n个字符(即n个结点)
if(n<=1)
return ;
int m = 2*n-1;//n个字符,需要构造2n-1个结点
HT = (HuffmanTree)malloc( (m+1)*sizeof(HTNode) );
HuffmanTree p;
int i;
int s1,s2;
for(p=HT+1, i=1; i<=n; i++, p++, w++)//n个字符(结点)初始化
{
//*p = {*w,0,0,0};
p->weight = *w;
p->lchild = 0;
p->rchild = 0;
p->parent = 0;
}
for(; i<=m; i++, p++)//后面结点初始化
{
p->weight = 0;
p->lchild = 0;
p->rchild = 0;
p->parent = 0;
}
for(i=n+1; i<=m; i++)// 建赫夫曼树
{ // 在HT[1~i-1]中选择parent为0且weight最小的两个结点,其序号分别为s1和s2
Select(HT,i-1,s1,s2);
HT[s1].parent = i;
HT[s2].parent = i;
HT[i].lchild = s1;
HT[i].rchild = s2;
HT[i].weight = HT[s1].weight + HT[s2].weight;
//cout<<i<<":"<<HT[s1].weight<<" "<<HT[s2].weight<<endl;
}
#define HC_1
#ifdef HC_1 //从叶子到根逆向求每个字符的哈弗曼编码
cout<<"从叶子到根"<<endl;
HC = (HuffmanCode)malloc( (n+1)*sizeof(char*) );
char *cd = (char*)malloc( n*sizeof(char));
cd[n-1] = '\0';//编码结束符
int start, c, f;
for(i=1; i<=n; i++)//逐个字符求哈弗曼编码
{
start = n-1;//编码结束位置
for(c=i, f=HT[i].parent; f!=0; c=f, f=HT[f].parent)//从叶子到根逆向求编码
{
if(HT[f].lchild == c)
cd[--start] = '0';
else
cd[--start] = '1';
}
HC[i] = (char*)malloc( (n-start)*sizeof(char) );//为第i个字符编码分配空间
strcpy(HC[i],&cd[start]);//从cd复制编码(串)到HC
}
free(cd);
#endif
//#define HC_2
#ifdef HC_2
cout<<"从根到叶子"<<endl;
HC = (HuffmanCode)malloc( (n+1)*sizeof(char*) );
char *cd = (char*)malloc( n*sizeof(char));
int num=m;
int cdlen = 0;
for(int i=1; i<=m; i++)
HT[i].weight = 0;//遍历哈弗曼树时用作结点状态标志
while(num)
{
if(HT[num].weight==0)//向左
{
HT[num].weight=1;
if(HT[num].lchild != 0)
{
num = HT[num].lchild;
cd[cdlen++] = '0';
}
else if(HT[num].rchild == 0)
{
HC[num] = (char*)malloc( (cdlen+1)*sizeof(char) );
cd[cdlen] = '\0';
strcpy(HC[num],cd);
}
}
else if(HT[num].weight == 1)//向右
{
HT[num].weight = 2;
if(HT[num].rchild != 0)
{
num = HT[num].rchild;
cd[cdlen++] = '1';
}
}
else//左右都遍历完后,退回到双亲结点
{
HT[num].weight = 0;
num = HT[num].parent;
--cdlen;
}
}
#endif
}
int main(int argc, char* argv[])
{
HuffmanTree T;
HuffmanCode HC;
cout<<"输入字符个数n(0~20):";
int n;
cin>>n;
int *weight = (int*)malloc( n*sizeof(int) );
int i;
for(i=0; i<n; i++)
{
cout<<"输入第"<<i+1<<"个字符的权重值:";
cin>>weight[i];
}
HuffmanCoding(T,HC,weight,n);
cout<<"哈弗曼编码"<<endl;
for(i=1; i<=n; i++)
{
cout<<"第"<<i<<"个字符编码:"<<HC[i]<<endl;
}
cout<<endl;
free(weight);
return 0;
}
数据结构--哈弗曼树
原文作者:哈夫曼树
原文地址: https://blog.csdn.net/dream_whui/article/details/44020803
本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
原文地址: https://blog.csdn.net/dream_whui/article/details/44020803
本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。