huffman树又叫最优二叉树,关于huffman和huffman树的定义在这里就不再说了,网上有很多。这里讲下实现的过程,各种各样的方法有很多,这里只是其中的一种。
分为5个文件,huffman.h、huffman.cpp、drawtree.h、drawtree.cpp、HuffmanTestApp.cpp。下面一一说明下用途:
1、huffman.h是huffman树和编码的头文件:
#ifndef _HUFFMAN_H_
#define _HUFFMAN_H_
#include <string.h>
#include <memory.h>
#include <stdlib.h>
#include <cstring>
#include <stdio.h>
#define MAX_CODES 1000
#define MAX_WEIGHT 0x7FFFFFFF
#define LEFT_CODE '0'
#define RIGHT_CODE '1'
typedef struct
{
unsigned int weight;
unsigned int parent, lchild, rchild;
}HTNode,*HuffmanTree;
typedef struct
{
char cd[MAX_CODES]; //这里本来是有别的信息的,后来删去了。
}HCode;
extern HCode hcd[MAX_CODES];
extern int Height;
extern int Hffuman_Nodes;
void BuildHuffmanTree(HuffmanTree& Hroot,int N,int* Message);
void Select(HuffmanTree& Hroot,int& x,int& y,int end);
void HuffmanCode(HuffmanTree& Hroot,char* code,int m,int k);
void FindHuffmanRoot(HuffmanTree& Hroot,int &k);
#endif //_HUFFMAN_H_
2、huffman.cpp文件是huffman.h的实现:
#include "Huffman.h"
int Height=0;
int Hffuman_Nodes=0;
HCode hcd[MAX_CODES];
void BuildHuffmanTree(HuffmanTree& Hroot,int N,int* Message)
{
int x,y,j,i=N+1,k;
char temp_code[1000]={0};
Hffuman_Nodes=N;
N=N*2;
Hroot = (HuffmanTree)malloc(sizeof(HTNode)*N);
memset(Hroot,0,sizeof(HTNode)*N);
Hroot[0].weight = MAX_WEIGHT;
for(j=1; j<i; j++)
Hroot[j].weight = Message[j-1];
while(i<N)
{
Select(Hroot,x,y,i);
Hroot[x].parent = i;
Hroot[y].parent = i;
Hroot[i].lchild = x;
Hroot[i].rchild = y;
Hroot[i].weight=Hroot[x].weight+Hroot[y].weight;
i++;
}
FindHuffmanRoot(Hroot,k);
HuffmanCode(Hroot,temp_code,0,k);
return ;
}
void Select(HuffmanTree& Hroot,int& x,int& y,int end)
{
int i;
x = y = 0;
for(i=1; i<end; i++)
{
if(Hroot[i].parent) continue;
if(Hroot[i].weight<Hroot[x].weight)
{
y = x;
x = i;
}
else if(Hroot[i].weight<Hroot[y].weight)
{
y = i;
}
}
return ;
}
void HuffmanCode(HuffmanTree& Hroot,char* code,int m,int k)
{
if(k==0) return ;
if(m>Height) Height=m;
if(!Hroot[k].lchild&&!Hroot[k].rchild)
{
code[m]=0;
strcpy(hcd[k].cd,code);
}
else
{
code[m]=LEFT_CODE;
HuffmanCode(Hroot,code,m+1,Hroot[k].lchild);
code[m]=RIGHT_CODE;
HuffmanCode(Hroot,code,m+1,Hroot[k].rchild);
}
return ;
}
void FindHuffmanRoot(HuffmanTree& Hroot,int &k)
{
for(k=1; ; k++)
if(!Hroot[k].parent)
break;
return ;
}
3、drawtree.h文件是图形相关文件,用于实现图形的:
#ifndef _DRAWTREE_H_
#define _DRAWTREE_H_
#include <stdio.h>
#include "graphics.h"
#include "Huffman.h"
#define DNodeRadius 30
#define DYoffset NodeRadius*3
#define NodeShape 0
#define Codeoffset 60
#define LineThickNess 2
#define TreeLeafColor BLUE
#define TreeBackColor WHITE
#define Win_Width 880
#define Win_Height 600
extern int NodeRadius;
extern int Yoffset;
void Draw(HuffmanTree& Hroot);
void DrawNode(HuffmanTree& Hroot,int x,int y,int k);
void DrawHuffmanTree(HuffmanTree& Hroot,int x,int y,int len,int k);
void ScanHuffmanCode(HuffmanTree& Hroot);
#endif //_DRAWTREE_H_
4、drawtree.cpp文件是drawtree.h的实现:
#include "DrawTree.h"
int NodeRadius=DNodeRadius,Yoffset=DYoffset;
void Draw(HuffmanTree& Hroot)
{
int k;
initgraph(Win_Width,Win_Height);
setcaption("Huffman Tree");
setbkcolor(WHITE);
line(Codeoffset,0,Codeoffset,Win_Height);
setcolor(GREEN);
outtextxy(Codeoffset+2,0,"Huffman Tree:");
setlinestyle(1,NULL,LineThickNess);
setbkmode(TRANSPARENT);
FindHuffmanRoot(Hroot,k);
if(Yoffset*(Height+1)>Win_Height)
Yoffset=Win_Height/(Height+1);
if((NodeRadius+2)*(1<<Height)*2>Win_Width-Codeoffset)
NodeRadius = (Win_Width-Codeoffset)/(1<<Height+1)-2;
if(Yoffset<0) Yoffset=1;
if(NodeRadius<0) NodeRadius=0;
DrawHuffmanTree(Hroot,getwidth()/2+Codeoffset/2,NodeRadius+10,(NodeRadius+2)*(1<<Height),k);
}
void DrawNode(HuffmanTree& Hroot,int x,int y,int k)
{
char temp_str[MAX_CODES];
setcolor(RED);
sprintf(temp_str,"%d",Hroot[k].weight);
if(!Hroot[k].lchild&&!Hroot[k].rchild)
setfillcolor(TreeLeafColor);
else
setfillcolor(TreeBackColor);
switch(NodeShape)
{
case 0:
fillellipse(x,y,NodeRadius,NodeRadius);
outtextxy(x-strlen(temp_str)*4,y-8,temp_str);
setcolor(GREEN);
circle(x,y,NodeRadius); break;
case 1:
bar(x-NodeRadius,y-NodeRadius,x+NodeRadius,y+NodeRadius);
outtextxy(x-strlen(temp_str)*4,y-8,temp_str);
setcolor(GREEN);
rectangle(x-NodeRadius,y-NodeRadius,x+NodeRadius,y+NodeRadius);
break;
}
}
void DrawHuffmanTree(HuffmanTree& Hroot,int x,int y,int len,int k)
{
if(!k) return;
len = len/2;
DrawNode(Hroot,x,y,k);
if(Hroot[k].lchild)
{
line(x,y+NodeRadius,x-len,y+Yoffset-NodeRadius);
DrawHuffmanTree(Hroot,x-len,y+Yoffset,len,Hroot[k].lchild);
}
if(Hroot[k].rchild)
{
line(x,y+NodeRadius,x+len,y+Yoffset-NodeRadius);
DrawHuffmanTree(Hroot,x+len,y+Yoffset,len,Hroot[k].rchild);
}
}
void ScanHuffmanCode(HuffmanTree& Hroot)
{
int i;
char temp_str[30];
outtextxy(0,0,"Code:");
for(i=1; i<=Hffuman_Nodes; i++)
{
sprintf(temp_str,"%2d: %s",i,hcd[i].cd);
outtextxy(0,20*i,temp_str);
}
}
5、HuffmanTestApp.cpp文件,实现测试功能:
#include <stdio.h>
#include <math.h>
#include "Huffman.h"
#include "DrawTree.h"
int main()
{
int n=6,weight[50]={1,2,3,4,5,6};
HuffmanTree h; //define huffman tree
BuildHuffmanTree(h,n,weight); //build tree
Draw(h); //draw huffman tree
ScanHuffmanCode(h); //scan Huffman code
getch();
return 0;
}
第一次运行会绘出一个测试huffman树,如下:
程序包可以在这下载:http://download.youkuaiyun.com/detail/decting/4793815