#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef unsigned int UINT;
typedef char ElemType;
typedef struct{
ElemType elem;
UINT weight;
UINT parent,lchild,rchild;
}HTNode, *HuffmanTree;
typedef char** HuffmanCode;
#define N 40
UINT Weight[N]; //用于记录以出现过的权值的下标
int wi = 0;
void HuffmanCoding(HuffmanTree&, HuffmanCode&, int *w, char *e,int n);
void Select(HuffmanTree, int, int&, int&);
void OutHuffmanInfo(HuffmanTree hTree, HuffmanCode hCode,int n);
int main()
{
printf("Text huffmanTree and huffmancode!/n");
HuffmanTree hTree = NULL;
HuffmanCode hCode = NULL;
char elem[]={"abcdefgh"};
int weight[]={5,29,7,8,14,23,3,11};
int n = 8;
HuffmanCoding( hTree, hCode, weight, elem, n);
OutHuffmanInfo(hTree,hCode,n);
system("PAUSE");
return 0;
}
void HuffmanCoding(HuffmanTree& hTree, HuffmanCode& hCode, int *w, char *e,int n)
{
if( n<=1) return;
int m = 2*n-1;
hTree = (HuffmanTree)malloc((m+1)*sizeof(HTNode));
HuffmanTree pTree = hTree+1;
int ix;
for(ix=1; ix<=n; ++ix,++pTree,++w,++e)
{
pTree->elem = *e;
pTree->weight = *w;
pTree->lchild = 0;
pTree->rchild = 0;
pTree->parent = 0;
}
for(; ix <=m; ++ix,++pTree)
{
pTree->elem = '/0';
pTree->lchild = 0;
pTree->parent = 0;
pTree->rchild = 0;
pTree->weight = 0;
}
for( ix=n+1; ix<=m; ++ix)
{
int s1=-1,s2=-1;
Select(hTree,ix-1,s1,s2);
//加判断主要为了防止到尾部时产生非法数据
if(s1!=-1) hTree[s1].parent = ix;
if(s2!=-1) hTree[s2].parent = ix;
if(s1!=-1) hTree[ix].lchild = s2; //这两个的指向顺序没有关系,可以让lchild = s1,rchild = s2
if(s2!=-1) hTree[ix].rchild = s1; //只不过产生不同的编码.
if(s1!=-1 && s2!=-1) hTree[ix].weight = hTree[s1].weight+hTree[s2].weight;
else if(s1!=-1) hTree[ix].weight = hTree[s1].weight;
else hTree[ix].weight = hTree[s2].weight;
}
//-------------从叶子到根逆向求编码--------------
hCode = (HuffmanCode)malloc((n+1)*sizeof(char*));
char *cd = (char*)malloc(n*sizeof(char)); //记录编码表
cd[n-1] = '/0';
for(ix=1; ix<=n; ++ix)
{
int start = n-1;
int cur = -1; //记录当前位置
int fpos = -1; //记录父结点位置
//这个for就是从叶子向根结点走,通过父结点的左或右孩子是否等于当前结点来得到编码
for( cur=ix, fpos=hTree[ix].parent; fpos!=0; cur=fpos,fpos=hTree[fpos].parent)
{
if(hTree[fpos].lchild == cur) cd[--start] = '0';
else cd[--start] = '1';
}
hCode[ix] = (char*)malloc((n-start)*sizeof(char));
strcpy(hCode[ix],&cd[start]);
}
free(cd);
}
//寻找树中权值最小的点.找到后把该位置记录下来,下次查找跳过该点
void Select(HuffmanTree hTree, int imax, int& s1, int& s2)
{
UINT temp1 = 10000;
UINT temp2 = 10000;
int pos = -1;
bool flag = true;
for(int ix = 1; ix<=imax; ++ix)
{ //第一次进来wi为空,进if产生第一个权值最小的pos
if(wi == 0)
{
if(temp1>hTree[ix].weight)
{
temp1 = hTree[ix].weight;
pos = ix;
}
}
else
{ //排除已取过值的下标
for(int jx = 0; jx < wi; jx++)
{
if(ix != Weight[jx]) flag = true;
else
{
flag = false;
break;
}
}
if(flag)
{
for(int jx = 0; jx<wi; ++jx)
{
if(temp1>hTree[ix].weight)
{
temp1 = hTree[ix].weight;
pos = ix;
}
}
}
}//else
}
Weight[wi++] = s1 = pos;
for(int ix = 1; ix<=imax; ++ix)
{
for(int jx = 0; jx < wi; jx++)
{
if(ix != Weight[jx]) flag = true;
else
{
flag = false;
break;
}
}
if(flag)
{
for(int jx = 0; jx<wi; ++jx)
{
if(temp2>hTree[ix].weight)
{
temp2 = hTree[ix].weight;
pos = ix;
}
}
}
}
Weight[wi++] = s2 = pos;
}
void OutHuffmanInfo(HuffmanTree hTree, HuffmanCode hCode,int n)
{
HuffmanTree outTree = hTree;
HuffmanCode outCode = hCode;
for(int ix = 1; ix<=n; ++ix)
{
printf("/n");
printf("第%d个字符: %c/t拥有权值为%d/t产生的编码是: %s/n",ix,outTree[ix].elem,outTree[ix].weight,outCode[ix]);
//printf("产生的编码是: %s/n",outCode[ix]);
printf("/n");
}
}
/*
//对hTree的生成顺序的跟踪结果
hTree 0x000332d8 HTNode * &
hCode 0x00000000 char * * &
hTree[15] {weight=100 parent=0 lchild=13 ...} HTNode
hTree[14] {weight=58 parent=15 lchild=2 ...} HTNode
hTree[13] {weight=42 parent=15 lchild=11 ...} HTNode
hTree[12] {weight=29 parent=14 lchild=5 ...} HTNode
hTree[11] {weight=19 parent=13 lchild=9 ...} HTNode
hTree[10] {weight=15 parent=12 lchild=3 ...} HTNode
hTree[9] {weight=8 parent=11 lchild=7 ...} HTNode
hTree[8] {weight=11 parent=11 lchild=0 ...} HTNode
hTree[7] {weight=3 parent=9 lchild=0 ...} HTNode
hTree[6] {weight=23 parent=13 lchild=0 ...} HTNode
hTree[5] {weight=14 parent=12 lchild=0 ...} HTNode
hTree[4] {weight=8 parent=10 lchild=0 ...} HTNode
hTree[3] {weight=7 parent=10 lchild=0 ...} HTNode
hTree[2] {weight=29 parent=14 lchild=0 ...} HTNode
hTree[1] {weight=5 parent=9 lchild=0 ...} HTNode
hTree[0] {weight=3452816845 parent=3452816845 lchild=3452816845 ...} HTNode
*/
huffman树的生成与编码的实现
最新推荐文章于 2017-04-11 20:09:37 发布