哈夫曼树编码译码

#include <iostream>

int n=0;
double a[200];
char  b[200];
int count=0;
typedef  struct{
    double weight;
    int parent;
    int lchild;
    int rchild;
    char s;
}HTNODE;
typedef  HTNODE Huffman[3000];

void InitHT(Huffman T) {
    for (int i = 0; i < 2*n-1; i++) {
        T[i].rchild = -1;
        T[i].lchild = -1;
        T[i].parent = -1;
        T[i].weight = 10;
    }
}

 void input(Huffman T)
{
    int i = 0;
    int flag = 0;
    for (int j = 0; j <= 126; j++) {
        a[j] = 0;
    }
    FILE *file = fopen("input.txt", "r");
    int ch;
    while ((ch = fgetc(file)) != EOF) {
        count++;
        for (int k = 0; k <= 126; k++) {
            if (b[k] == ch) {
                flag = 1;
            }
        }
        if (flag == 0) {
            n++;
        }
        for (i = 0; i <= 126; i++) {
            if (ch == i) {
                a[i]++;
                b[i]=ch;
                break;
            }
        }
        flag = 0;
    }
    fclose(file);
}

void set(Huffman T)
{
    int y=0;
    for(int g=0;g<=126;g++)
    {
        if(a[g]!=0)
        {
            T[y].weight=a[g]/count;
            T[y].s=b[g];
            y++;
        }
    }
}




int z1;
int z2;
void Selecttwomin(Huffman T,int x,int *m1,int*m2)
{
    double min1 =999;
    double min2 =999;
    int j;
    int k;
    for(j=0;j<=x;j++)
    {
        if(T[j].weight<min1 && T[j].parent==-1)
        {
            min1=T[j].weight;
            *m1=j;
            z1=*m1;
        }
    }
//    printf("%d\n",z1);

    for(k=0;k<=x;k++)
    {
        if(T[k].weight<min2 &&T[k].parent==-1 && k!=z1)
        {
            min2=T[k].weight;
            *m2=k;
            z2=*m2;
        }
    }
//    printf("%dok\n",*m2);

}

void CreatHuffmanTree(Huffman T,int n)
{
    int i,m1,m2;
    for(i=n;i<2*n-1;i++)
    {
        Selecttwomin(T,i,&m1,&m2);
        T[i].weight=T[z1].weight+T[z2].weight;
        T[z1].parent=T[z2].parent=i;
        T[i].parent=-1;
        T[i].lchild=z1;
        T[i].rchild=z2;
    }
//    printf("%d\n",T[4].lchild);
}

 void createcode(Huffman T,int n,char **hc)
 {
     char * cd =(char*) malloc(n*sizeof(char) );
    cd[n-1]='\0';
    int now=0;
    int i=0;
    int p=0;
    while(i<n)
    {
        int start=n;
        memset(cd, 0, n); // 清空cd数组
        now=i;
        p=T[now].parent;
        while(p!=-1)
        {
            start--;
            if(now==T[p].lchild)
            {
//                printf("%d加一啦",now);
                cd[start]='1';

            } else
            {
//                printf("%d加0啦",now);
                cd[start]='0';
            }
            now=p;
            p=T[p].parent;
//            printf("p的值为%d\n",p);
        }
        hc[i]=(char*)malloc((n-start)*sizeof(char));
        strcpy(hc[i],&cd[start]);
//        printf("%s",hc[i]);
        i++;
    }
//     printf("%s\n",hc[3]);

 }

 void printf(Huffman T,char **hc,int index)
 {
    if(index>=0)
    {
        if(T[index].lchild==-1&&T[index].rchild==-1)
        {
            printf("%c:%s\n",T[index].s,hc[index]);
            return ;
        }
        printf(T,hc,T[index].lchild);
        printf(T,hc,T[index].rchild);
    }
 }


void bianma(Huffman T, char **hc)
{
    FILE *input = fopen("input.txt", "r");
    FILE *output = fopen("compressed.bin", "a"); // 打开文件以追加方式写入

    if (input == NULL || output == NULL) {
        printf("无法打开文件\n");
        return;
    }
    int ch;
    int i=0;
    while ((ch = fgetc(input)) != EOF)
    {
        while(i<n) {
            if (ch == T[i].s)
            {
             fprintf(output,"%s",hc[i]);
            }
            i++;
//            printf("循环一次!\n");
        }
     i=0;
    }
    fclose(input);
    fclose(output);
}

void yima(Huffman T)
{
    FILE *file = fopen("compressed.bin", "r");
    FILE *thelast = fopen("thelast.txt", "a"); // 打开文件以追加方式写入

    char ch;
    int i=2*n-2;
    while((ch = fgetc(file)) != EOF)
    {
if(ch=='0') {
    i = T[i].rchild;
    if (T[i].lchild == -1 && T[i].rchild == -1) {
        fprintf(thelast,"%c", T[i].s);
        i = 2 * n - 2;
    }
}
if(ch=='1')
{
 i=T[i].lchild;
    if(T[i].lchild==-1&&T[i].rchild==-1) {
        fprintf(thelast,"%c", T[i].s);
        i = 2 * n - 2;
    }
}
}
    fclose(file);
fclose(thelast);
}

void yasuo()
{
    const char *originalFileName = "input.txt";
    const char *compressedFileName = "compressed.bin"; // 假设是用二进制格式保存的压缩文件

    // 获取原始文件大小
    FILE *originalFile = fopen(originalFileName, "rb");
    fseek(originalFile, 0, SEEK_END);
    long originalSize = ftell(originalFile);
    fclose(originalFile);

    // 获取压缩后文件大小
    FILE *compressedFile = fopen(compressedFileName, "rb");
    fseek(compressedFile, 0, SEEK_END);
    long compressedSize = ftell(compressedFile)/8;
    fclose(compressedFile);

    // 计算压缩率
    double compressionRatio = 1.0 - ((double)compressedSize / (double)originalSize);
    // 将压缩率转化为百分比
    double compressionPercentage = compressionRatio * 100.0;

    printf("原始文件大小:%ld 字节\n", originalSize);
    printf("压缩后文件大小:%ld 字节\n", compressedSize);
    printf("压缩率:%.2f%%\n", compressionPercentage);
}

 void compare()
 {
     FILE *file = fopen("input.txt", "r");
     FILE *file1 = fopen("thelast.txt", "r");
     if (file1 == NULL) {
         printf("无法打开文件\n");
         return;
     }
    while(1)
    {
         char ch = fgetc(file);
         char ch1 = fgetc(file1);
//        printf("%c",ch);
//        printf("%c",ch1);
        if(ch!=ch1)
        {
            printf("我们不一样!");
            break;
        }
        if(ch==EOF && ch1==EOF)
        {
            printf("其实我们都一样!");
            break;
        }
    }
     fclose(file);
     fclose(file1);
 }

int main() {

    Huffman  T;
    input(T);
    InitHT(T);
    set(T);
    CreatHuffmanTree( T, n);
    char *hc[n+1];
    createcode(T,n,hc);
    printf(T,hc,2*n-2);
    bianma(T,hc);
    yima(T);
    yasuo();
    compare();
//    FILE *file = fopen("compressed.bin", "w"); // 以写入方式打开文件,将清空文件内容
//    if (file == NULL) {
//        printf("无法打开文件\n");
//        return 1;
//    }
//    fclose(file); // 立即关闭文件以确保内容被清空
//    printf("文件内容已清空\n");
    return 0;
 }
我是跟着B站上的一个up主写的,有改动。

视频地址如下:数据结构课设之哈夫曼树编码译码代码讲解_哔哩哔哩_bilibili

之前我的实验都是抄的,或者直接让g p t生成,这次算是一个新开始,加油!

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值