#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 */