赫夫曼树的代码 注意 我的代码都是在vs2010上运行通过的 在其他编译器上面不一定完全是好的 #define DEBU #include<iostream> using namespace std; typedef struct{ unsigned int weight; unsigned int parent,lchild,rchild; }HTNode,*HuffmanTree; typedef char * *HuffmanCode; typedef struct{ char text; int weight; }charWeight; int getLength(charWeight *cw) { #ifdef DEBUG //cout<<"求得cw长度为"<<cw[0].weight<<"/n"; #endif return cw[0].weight; } bool isDifferent(charWeight *cw,char x) { int i=1,j=getLength(cw); for(i=1;i<=j;i++) { if(x==cw[i].text) { #ifdef DEBUG cout<<"相同字符"<<x<<"/n"; #endif cw[i].weight++; return false; } } if(i>=j) { #ifdef DEBUG cout<<"发现新字符"<<x<<",添加到cw中"<<"/n"; #endif cw[j+1].text=x; cw[j+1].weight=1; cw[0].weight++; return true; } return -1; } void Select(HuffmanTree &HT, int i, int &s1, int &s2) { s1=0;s2=0;//初始 //while(HT[s1].parent!=0)s2=++s1; for(int num=1;num<=i;num++) { if(HT[num].parent==0&&s1==0)//parent==0进行比较 s1=num; else if(HT[num].parent==0&&s1!=0) if(HT[num].weight<HT[s1].weight) s1=num; } for(int num=1;num<=i;num++) { if(HT[num].parent==0&&s2==0&&num!=s1)//parent==0进行比较 s2=num; else if(HT[num].parent==0&&s2!=0&&num!=s1) if(HT[num].weight<HT[s1].weight) s2=num; } #ifdef DEBUG cout<<"进入select,得到s1="<<s1<<" s2="<<s2<<"/n"; #endif } void HuffmanCoding(HuffmanTree &HT, HuffmanCode &HC, int w[129], int n) { // w存放n个字符的权值(均>0),构造哈夫曼树HT, // 并求出n个字符的哈夫曼编码HC int i=1, m, s1, s2, start; char *cd; unsigned int c, f; if (n<=1) return; m = 2 * n - 1; HT = (HuffmanTree)malloc((m+1) * sizeof(HTNode)); // 0号单元未用 HT[0].parent=m;//存储根节点 for (i=1; i<=n; i++) { //*初始化 //HT[i].weight=w[i-1];错误w为指针 HT[i].weight=w[i-1]; HT[i].parent=0; HT[i].lchild=0; HT[i].rchild=0; } for (i=n+1; i<=m; i++) { //初始化 HT[i].weight=0; HT[i].parent=0; HT[i].lchild=0; HT[i].rchild=0; } for (i=n+1; i<=m; i++) { // 建哈夫曼树 // Select 在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; } //--- 从叶子到根逆向求每个字符的哈夫曼编码 --- HC = (HuffmanCode)malloc((n+1)*sizeof(char *));//分配n个字符编码的头指针向量 cd = (char *)malloc(n*sizeof(char)); // 分配求编码的工作空间 cd[n-1] = '/0'; // 编码结束符。 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 #ifdef DEBUG cout<<"cd编码为:"<<cd[start]<<"/n"; cout<<"HC["<<i<<"]编码为:"<<HC[i]<<"/n"; #endif } free(cd); // 释放工作空间 } void printHuffmanTreeCode(HuffmanTree &HT,HuffmanCode &HC,int n,charWeight *cw) { int i=1; cout<<"i"<<" "<<"HT[i].weight"<<" "<<"HT[i].parent"<<" "<<"HT[i].lchild"<<" "<<"HT[i].rchild"<<" "<<"HC[i]"<<"/n"; for(i=1;i<=n;i++) cout<<i<<" "<<HT[i].weight<<" "<<HT[i].parent<<" "<<HT[i].lchild<<" "<<HT[i].rchild<<" "<<HC[i]<<" "<<cw[i].text<<"/n"; } void getWeight(int *w,int &n,charWeight *cw) { int i=0; char x='#'; char *inputchar=(char*) malloc(1000*sizeof(char)); cin.getline(inputchar,1000); cout<<inputchar; cw[0].weight=0; x=inputchar[i]; while(x!='#') { isDifferent(cw,x); x=inputchar[++i]; } //w=(int)malloc(getLength(cw)*sizeof(int)); for(int j=1;j<=getLength(cw);j++) { //w[j-1]=cw[j].weight; //错误提示:下标要求数组或指针类型 w[j-1]=cw[j].weight; //w++; #ifdef DEBUG cout<<"w"<<"["<<j-1<<"]="<<w[j-1]<<"/n"; #endif } n=getLength(cw); #ifdef DEBUG cout<<"字符个数"<<n<<"/n"<<"得到的charWeight为:"<<"/n"; cout<<"i "<<"text "<<"weight "<<"/n"; for(int i=0;i<=cw[0].weight;i++) { cout<<i<<" "<<cw[i].text<<" "<<cw[i].weight<<"/n"; } #endif } void readCode(HuffmanTree HT,HuffmanCode HC,charWeight *cw) { int i=0,x=0; int l=HT[0].parent; char *inputCode; inputCode=(char *)malloc(100*sizeof(char)); cin>>inputCode; while(x!='#'-'0') { #ifdef DEBUG cout<<"进入read循环,i="<<i<<"/n"; #endif #ifdef DEBUG cout<<"X赋值前,x="<<x<<"/n"; #endif x=inputCode[i]-'0'; i++; #ifdef DEBUG cout<<"X赋值后,x="<<x<<"/n"; #endif if(x==0&&HT[l].lchild) { l=HT[l].lchild; #ifdef DEBUG cout<<"l=HT[l].lchild"<<"/n"; #endif } else if(x==1&&HT[l].rchild) { l=HT[l].rchild; #ifdef DEBUG cout<<"l=HT[l].rchild"<<"/n"; #endif } if(!HT[l].rchild&&!HT[l].lchild) { #ifdef DEBUG cout<<"找到节点,并输出:"<<cw[l].text<<"/n"; #endif cout<<cw[l].text; l=HT[0].parent; } } } void main() { HuffmanTree HT; HuffmanCode HC; charWeight *cw; cw=(charWeight *)malloc(129*sizeof(charWeight)); int w[129]={}; int n=0; getWeight(w,n,cw); HuffmanCoding(HT,HC,w,n); printHuffmanTreeCode(HT,HC,n,cw); readCode(HT,HC,cw); system("pause"); } /* int main() { FILE *fp; char ch; if((fp=fopen("test.txt","w"))==NULL) { printf("cannot open file!/n"); exit(0); } while((ch=_fgetchar())!='/n') { fputc(ch,fp); cout<<ch; } fclose(fp); }*/