目录
最终结果展示
总体大纲
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#define N 999
char c[N];//存储不同的字符
int weight[N];//存储各个字符的权值
typedef struct hf{
char ch;
int weight;
int parent;
int lchild;
int rchild;
}Huffman;
void HuffmanTree(Huffman huffTree[],char s[],int n);//构造一个Huffman树
void HuffmanCode(Huffman huffTree[],int n);//用来生成Huffman编码并输出
void HuffmanCode1(Huffman huffTree[],int n,char* s);//用来实现译码
void select(Huffman huffTree[],int k,int *i1,int *i2);//找到最小和次最小的节点
void count(int zhenfule[],char s[],char c[]);//用来记录输入的字符串中不同字母的权值
void strcpys(char* s1,char *s2,int n);//复制字符串
int numString(char s[]);//用来求字符串中有几种不同的字符
//界面函数
void menu();
void print(Huffman huffTree[],int n,char *s);
哈夫曼树构建函数
//构建哈夫曼树
void HuffmanTree(Huffman huffTree[],char s[],int n){
count(weight,s,c);
int i1,i2;
for(int i=0;i<2*n-1;i++){//进行树的初始化
if(i<n){
huffTree[i].ch=c[i];
}
huffTree[i].parent=-1;
huffTree[i].lchild=-1;
huffTree[i].rchild=-1;
}
for(int i=0;i<n;i++){
huffTree[i].weight=weight[i];
}
for(int k=n;k<2*n-1;k++){
select(huffTree,k,&i1,&i2);//找到parent为-1的最小和次小的节点
huffTree[k].weight=huffTree[i1].weight+huffTree[i2].weight;
huffTree[i1].parent=k;
huffTree[i2].parent=k;
huffTree[k].lchild=i1;
huffTree[k].rchild=i2;
}
}
//构建哈夫曼树的附带函数————找到最小和次最小节点
void select(Huffman huffTree[],int k,int *i1,int *i2){
int min1=99999;
int min2=99999;
int i;
for(i=0;i<k;i++){//找到i1
if(huffTree[i].weight<min1&&huffTree[i].parent==-1){
min1=huffTree[i].weight;
*i1=i;
}
}
for(i=0;i<k;i++){//找到i2
if(huffTree[i].weight<min2&&huffTree[i].parent==-1){
if(i!=*i1){
min2=huffTree[i].weight;
*i2=i;
}
}
}
}
哈夫曼编码函数
//编码
void HuffmanCode(Huffman huffTree[],int n){
int start,pos,parent;
char temp[n];
char temp1[n];
temp[n-1]='\0';
for(int i=0;i<n;i++){//依次向上遍历树,找到他所对应的码值
start=n-1;
pos=i;
parent=huffTree[i].parent;
while(parent!=-1){
if(huffTree[parent].lchild==pos){
temp[--start]='0';
}else{
temp[--start]='1';
}
pos=parent;
parent=huffTree[parent].parent;
}
strcpys(temp1,temp,start);
int j=0;
printf("%c的码值----",c[i]);
while(temp1[j]!='\0'){
printf("%c ",temp1[j]);
j++;
}
printf("\n");
}
}
//编码附带函数————进行复制
void strcpys(char s1[],char s2[],int n){
int i=0;
while(s2[n]!='\0'){
s1[i]=s2[n];
i++;
n++;
}
s1[i]='\0';
}
哈夫曼译码函数
//译码
void HuffmanCode1(Huffman huffTree[],int n,char* s){
int i=2*n-1-1;
while(*s!='\0'){
if((*s)=='0'){
i=huffTree[i].lchild;
}else{
i=huffTree[i].rchild;
}
if(huffTree[i].lchild==-1){
printf("%c",huffTree[i].ch);
i=2*n-2;
}
s++;
}
}
求取输入的字符串中不同的字符种类的函数
//用来求字符串中有几种不同的字符
int numString(char s[]){
char c[N];
char temp1[999]={0};
int i=0;
int j=0;
while(s[j]!='\0'){
if(temp1[s[j]]==0){
c[i]=s[j];
temp1[s[j]]++;
i++;
}
j++;
}
return strlen(c);
}
//把字符串中不同的字符提取出来
void cop(char c[],char s[]){
char temp1[999]={0};
int i=0;
int j=0;
while(s[j]!='\0'){
if(temp1[s[j]]==0){
c[i]=s[j];
temp1[s[j]]++;
i++;
}
j++;
}
}
计算字符权值的函数
//用来记录输入的字符串中不同字母的权值
void count(int zhenfule[],char s[],char c[]){//c用来记录输入的字符串中有几种字符,cout用来记录各种字符出现的次数
char temp1[999]={0};
int i=0;
int j=0;
while(s[j]!='\0'){
if(temp1[s[j]]==0){
c[i]=s[j];
temp1[s[j]]++;
i++;
}
j++;
}
int fule[numString(s)]={0};
for(int j=0;j<strlen(c);j++){
int m=0;
while(s[m]!='\0'){
if(s[m]==c[j]){
fule[j]++;
}
m++;
}
}
for(int i=0;i<numString(s);i++){
zhenfule[i]=fule[i];
}
}
菜单函数
void menu(){
printf("\t\t◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆\n");
printf("\t\t* ********哈夫曼编码/译码器******** *\n");
printf("\t\t* 1.创建哈夫曼树; *\n");
printf("\t\t* 2.输出字符个数以及各字符权值 *\n");
printf("\t\t* 3.进行哈夫曼编码; *\n");
printf("\t\t* 4.进行哈夫曼译码; *\n");
printf("\t\t* 5.退出; *\n");
printf("\t\t◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆\n");
}
void print(Huffman huffTree[],int n,char *s){
count(weight,s,c);
printf("不同的字符数:%d\n",n);
for(int i=0;i<n;i++){
if(i!=n-1)
printf("%c的权值:%d\n",c[i],weight[i]);
else{
printf("%c的权值:%d",c[i],weight[i]);
}
}
printf("\n");
printf("字符 节点i 权值 左孩子 右孩子 双亲节点\n");
for(int i=0;i<n*2-1;i++){
if(i<n){
printf("%c %7d %7d %7d %8d %10d\n",c[i],i,huffTree[i].weight,huffTree[i].lchild,huffTree[i].rchild,huffTree[i].parent);
}
else{
printf("%9d %7d %6d %8d %11d\n",i,huffTree[i].weight,huffTree[i].lchild,huffTree[i].rchild,huffTree[i].parent);
}
}
}
主MAIN函数
int main(){
menu();
char ch;
int n;
do{
Huffman huffTree[N];
char s1[N];
printf("请输入一段字符串");
scanf("%s",s1);
count(weight,s1,c);
HuffmanTree(huffTree,s1,numString(s1));
printf("请选择要执行的操作:\n");
scanf("%d",&n);
while(n!=5){
switch(n){
case 1:{
print(huffTree,numString(s1),s1);
break;
}
case 2:{
count(weight,s1,c);
printf("不同的字符数:%d\n",numString(s1));
for(int i=0;i<numString(s1);i++){
printf("%c权值:%d\n",c[i],weight[i]);
}
break;
}
case 3:{
printf("输出每个叶子的哈夫曼编码:\n");
HuffmanCode(huffTree,numString(s1));
break;
}
case 4:{
printf("请输入电文:\n");
char s2[N];
scanf("%s",s2);
printf("输出哈夫曼译码:\n");
HuffmanCode1(huffTree,numString(s1),s2);
printf("\n");
break;
}
}
printf("请输入接下来要执行的操作:");
scanf("%d",&n);
getchar();
}
fflush(stdin);
printf("你是想要继续输入新的字符串还是退出程序(y/n)?");
ch=getchar();
if(ch=='y'){
system("cls");
menu();
}
}while(ch!='n');
}
结果展示
代码都是手写的,实属不易,希望对大家有帮助!!!