前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >数据结构 哈夫曼编码/译码器

数据结构 哈夫曼编码/译码器

作者头像
川川菜鸟
发布于 2021-10-18 08:37:20
发布于 2021-10-18 08:37:20
76500
代码可运行
举报
运行总次数:0
代码可运行

题目8:哈夫曼编码/译码器 实验类型(验证/设计/创新):设计 学时:16 课程设计内容: 设计一个哈夫曼编码/译码系统,对一个文本文件中的字符进行哈夫曼编码,生成编码文件;反过来,可将一个编码文件译码还原为一个文本文件(.txt)。要求: 7.输入一个待压缩的文本文件名, 统计文本文件中各字符的个数作为权值,生成哈夫曼树; 8.将文本文件利用哈夫曼树进行编码,生成压缩文件; 9.输入一个待解压的压缩文件名称,并利用相应的哈夫曼树将编码序列译码; 10.可显示指定的压缩文件和文本文件; 课程设计要求: 熟练掌握哈夫曼树的构建方法;能够运用哈夫曼树实现哈夫曼编码和译码。 重点难点: 【本课程设计重点】哈夫曼树的构建和哈夫曼编码。 【本课程设计难点】各字符出现频率的统计、哈夫曼树的构建和哈夫曼译码。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
//
// Created by andyzhong on 2021/7/1.
//
#include

#include

#include

#include



using namespace std;



char filenamemi[100];

char filefile[100];

char filebian[100];



typedef struct

{
    int weight;

    char flag;

    int parent, lchild, rchild;

} HTNode, *HuffmanTree;

typedef struct ASCII

{
    char flag;

    int c;

    struct ASCII *next;

} ASCII, *LinkList;

typedef struct txt

{
    char flag;

    char huffman[5000];

} txtNode;



LinkList L;

typedef char **HuffmanCode;



bool InitList(LinkList &L)//初始化链表

{
    L = new ASCII;

    L->c  = 1;

    L->next = NULL;

    return true;

}



void Show(LinkList L)//显示链表

{
    LinkList p;

    p = L->next;

    while(p)

    {
        printf("  %c, %d\n", p->flag, p->c);

        p = p->next;

    }

    cout<<endl;

}



int Choice() //选择文件以及创建权重值

{
    FILE *fp;

    char a;

    int num = 0, key = 0;

    int instance = 0;

    LinkList  p, s, m;

    InitList(L);

    s = L;

    m = L;

    getchar();

    //char filefile[100] ;

    while(!key)

    {
        printf("请输入你要打开的文件名及路径,如c:\\users\\lenovo\\desktop\\7\\1.txt\n");

        gets(filefile);

        if ((fp=fopen(filefile,"r"))==NULL)

        {
            printf("打开文件%s出现错误\n",filefile);

            key = 0;

            return 0;

        }

        key = 1;

    }



    while((a = fgetc(fp)) != EOF)

    {
        s = L->next;

        printf("%c ", a);

        while(s)

        {
            if(s->flag == a)//如果在文本中出现了, 当前字符, 那么当前字符的权重值++

            {
                s->c++;

                instance = 1;

                break;

            }

            s = s->next;

        }

        if(instance == 0)//如果当前文本没有该字符, 那么, 创建该字符,插入到文本当中

        {
            p = new ASCII;

            p->flag = a;

            p->c = 1;

            m->next = p;

            p->next = NULL;

            m = p;

            num++;//文本中多少结点

        }

        instance = 0;

    }

    cout<<endl;

    Show(L);

    fclose(fp);

    return num;

}



void Select(HuffmanTree &HT, int num, int *s1, int *s2) //寻找两个最小的且双亲为0的最小节点

{
    int i, sec = 0, fir = 0;//a是次小, b是最小

    int second = -1, first = -1;

    HTNode L1, L2;//L1次小, L2最小

    for(i = num; i >= 1; i--)//选择两个双亲部不为0的结点

    {
        if(HT[i].parent == 0 && second == -1) second = i;

        else if(HT[i].parent == 0 && first == -1) first = i;



        if(first!=-1 && second!=-1) break;

    }

    //cout<

    if(HT[second].weight > HT[first].weight)

    {
        L1 = HT[second];

        L2 = HT[first];

        sec = second;

        fir = first;

    }

    else

    {
        L1 = HT[first];

        L2 = HT[second];

        sec = first;

        fir = second;

    }



    for(i = num; i >= 1; i--)//从剩下的节点中找到两个最小的节点

    {
        if( (HT[i].weight < L2.weight) &&(HT[i].parent == 0) && i!=second && i!=first)

        {
            L1 = L2;

            L2 = HT[i];

            sec = fir;

            fir = i;

        }

        else if( (HT[i].weight < L1.weight) && (HT[i].parent == 0) && i!=second && i!=first)

        {
            L1 = HT[i];

            sec = i;

        }

    }

    *s1 = fir;

    *s2 = sec;

}



bool CreatHuffmanaTree(HuffmanTree &HT, int num) //创建哈夫曼树

{
    int m, i;

    LinkList p;

    p = L->next;

    if(num <= 1) return false;

    m = 2*num-1;

    HT = new HTNode[m+1];

    for(i = 1; i <= m; i++)

    {
        HT[i].parent = 0;

        HT[i].lchild = 0;

        HT[i].rchild = 0;

    }

    for(i = 1; i <= num; i++)

    {
        HT[i].weight = p->c;

        HT[i].flag = p->flag;

        p = p->next;

    }



    int s1=0, s2=0;

    for(i = num+1; i <= m; i++)

    {
        Select(HT, i-1, &s1, &s2);

        //cout<

        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;

    }

    return true;

}



bool CreatHuffmanaCode(HuffmanTree HT, int num) //创建哈夫曼编码

{
    char  *cd;

    int i, c, f, start, key = 0;

    FILE *fp;

    char flag;

    getchar();

    while(!key)

    {
        printf("请输入你要保存密码本的文件名及路径,如c:\\users\\lenovo\\desktop\\7\\密码本.txt\n");

        gets(filenamemi);

        if ((fp=fopen(filenamemi,"w"))==NULL)

        {
            printf("保存文件%s出现错误, 请重新输入\n",filenamemi);

            key = 0;

        }

        key = 1;

    }

    cd = new char[num];

    cd[num-1] = '\0';

    for(i = 1; i <= num; i++)

    {
        start = num-1;

        c = i;

        f = HT[i].parent;

        flag = HT[i].flag;

        while(f != 0)

        {
            --start;

            if(HT[f].lchild == c) cd[start] = '0';

            else cd[start] = '1';

            c = f;

            f = HT[f].parent;

        }

        printf("%c %s\n", flag, &cd[start]);

        fprintf(fp,"%c %s\n", flag, &cd[start]);

    }

    delete cd;

    fclose(fp);

}

bool CreatTxtCode(int num)//创建文本编码

{
    FILE *fp, *fp1, *fp2;

    int key = 0;

    //char filename[100];

    txtNode txt[257];

    char a;

    getchar();

    while(!key)

    {
        printf("请输入你要保存编码的文件名及路径,如c:\\users\\lenovo\\desktop\\7\\1.cod\n");

        gets(filebian);

        if ((fp=fopen(filebian,"w"))==NULL)

        {
            printf("保存文件%s出现错误, 请重新输入\n",filebian);

            key = 0;

        }

        key = 1;



    }

    int i = 0, nu = 1, j;

    fp1 = fopen(filenamemi,"r");

    fp2 = fopen(filefile,"r");

    char interim[1000];

    fgets(interim, 100, fp1);

    while(!feof(fp1))

    {
        txt[nu-1].flag = interim[0];

        i = strlen(interim);

        for(j = 2; j < i-1; j++)

        {
            txt[nu-1].huffman[j-2] = interim[j];

        }

        fgets(interim, 100, fp1);

        nu++;

    }

    for(i = 0; i <= nu; i++)

    {
        cout<<txt[i].flag<<"  "<<txt[i].huffman<<endl;

    }

    while((a = fgetc(fp2)) != EOF)

    {
        for(i = 0; i <= nu; i++)

        {
            if(a == txt[i].flag)

            {
                fprintf(fp,"%s",txt[i].huffman);

            }

        }

    }

    fclose(fp);

    fclose(fp1);

    fclose(fp2);

    return true;

}

bool ReductionTxt(HuffmanTree HT, int num)//创建文本节点

{
    FILE *fp, *fp1;//fp----编码文件    fp1------还原之后的文件

    int key = 0;

    char filename[100],  filename1[100];

    char a;

    getchar();

    if ((fp=fopen(filebian,"r"))==NULL)

    {
        printf("打开文件%s出现错误\n",filebian);

        key = 0;

        return false;

    }

    while(!key)

    {
        printf("请输入你要保存的文件名及路径,如c:\\users\\lenovo\\desktop\\7\\2.txt\n");

        gets(filename1);

        if ((fp1=fopen(filename1,"w"))==NULL)

        {
            printf("打开文件%s出现错误\n",filename1);

            key = 0;

            return false;

        }

        key = 1;

    }



    int kk = 2*num-1;

    while((a = fgetc(fp)) != EOF)

    {
        if(a == '0')

        {
            kk = HT[kk].lchild;

        }

        else

        {
            kk = HT[kk].rchild;

        }



        if( (HT[kk].lchild == 0)  && (HT[kk].rchild == 0) )

        {
            fprintf(fp1,"%c", HT[kk].flag);

            kk = 2*num-1;

        }

    }

    fclose(fp);

    fclose(fp1);

    return true;

}



void zip()//压缩文件

{
    int fpnumber=0,fp1number=0;

    FILE *fp, *fp1;//fp----编码文件    fp1------压缩文件

    int key = 0, in, i;

    char filename[100],  filename1[100];

    char a;

    int twopower[11] = {1,2,4,8,16,32,64,128,256,512,1024};

    getchar();

    if ((fp=fopen(filebian,"r"))==NULL)

    {
        printf("打开文件%s出现错误\n",filebian);

        key = 0;

        return;

    }

    key = 0;

    while(!key)

    {
        printf("请输入保存的文件名及路径,如C:\\users\\lenovo\\desktop\\7\\2.cod\n");

        gets(filename1);

        if ((fp1=fopen(filename1,"w"))==NULL)

        {
            printf("打开文件%s出现错误\n",filename1);

            key = 0;

            return ;

        }

        key = 1;

    }

    //fp1=fopen("C:\\users\\lenovo\\desktop\\7\\2.cod","w");

    in = 0;

    int sum = 0, fla = 2;

    a = fgetc(fp);

    while(!feof(fp))

    {
        sum = sum + int(a-'0')*twopower[7-in];

        //cout<

        in++;

        a = fgetc(fp);

        if(in == 8 || feof(fp))

        {
            in = 0;

            fprintf(fp1, "%d ", sum);

            sum = 0;

        }

    }

    fseek(fp,0L,SEEK_END);   /*利用fseek函数将指针定位在文件结尾的位置*/

    fpnumber=ftell(fp);   /*利用ftell函数返回指针相对于文件开头的位置,以字节计算*/

    printf("原文件所占的字节数为%ld个\n",fpnumber);   /*进行输出*/

    fseek(fp1,0L,SEEK_END);   /*利   用fseek函数将指针定位在文件结尾的位置*/

    fp1number=ftell(fp1);   /*利用ftell函数返回指针相对于文件开头的位置,以字节计算*/

    printf("压缩后所占的字节数为%ld个\n",fp1number);   /*进行输出*/

    printf("压缩比为%d/%d",fp1number,fpnumber);

    fclose(fp);

    fclose(fp1);

}





int main()

{
    int num;

    HuffmanTree L;

    start:

    printf("******************************************************************\n\n");

    printf("哈夫曼编码译码器\n\n");

    printf("*\t1、选择需要进行编码的文件\t\t*\n\n");

    printf("*\t2、建立哈夫曼树\t\t\t\t*\n\n");

    printf("*\t3、建立密码本并对文件编码\t\t*\n\n");

    printf("*\t4、选择需要进行解码的文件并解码\t\t*\n\n");

    printf("*\t5、按位压缩方式对文件进行压缩\t\t*\n\n\n");

    printf("******************************************************************\n\n");

    int option = 0;

    cin>>option;

    while(1)

    {
        switch(option)

        {
            case 1:

                num = Choice();

                break;

            case 2:

                if(CreatHuffmanaTree(L, num))cout<<"成功"<<endl;

                break;

            case 3:

                CreatHuffmanaCode(L, num);

                if(CreatTxtCode(num)) cout<<"成功"<<endl;

                break;

            case 4:

                if(ReductionTxt(L, num)) cout<<"成功"<<endl;

                break;

            case 5:

                zip();

                cout<<"压缩成功";

                break;

        }

        goto start;

    }

    return 0;

}

运行结果:

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2021/07/07 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
数据结构之哈夫曼树和编码器的构造
在最近的自学数据结构的过程中,为加深树的理解,码了一个二叉树编码器,请多多指教: ---- #include #define MAXBIT100 //最大子树 #define MAXVALUE10000 //最大值 #define MAXLEAF30 //最大编码数 #define MAXNODEMAXLEAF*2 -1 //最大节点数 typedef struct { int bit[MAXBIT]; int start; } HCodeType;/*编码结构体*/ typedef struct { i
云时之间
2018/04/11
6550
数据结构——HuffmanTree
Huffman tree 基本术语 路径和路径长度 - 路径:在一棵树中,从一个结点往下可以达到的孩子或子孙结点之间的通路。 - 结点的路径长度:从一个结点到另一个结点的路径上分支的数目。 结点的权及带权路径长度 - 结点的权:将树中结点赋予一个有着某种含义的数值。 - 结点的带权路径长度:从根结点到该结点之间的路径长度与该结点的权的乘积。 树的带权路径长度 - 树中所有叶子结点的带权路径长度之和。 赫夫曼树( Huffman tree ) - 带权路径长度达到最小的二叉树即为赫夫曼
ruochen
2021/06/29
2420
数据结构——HuffmanTree
C语言火车订单管理源码
#include <conio.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <dos.h> /*公众号:C语言与CPP编程回复“源码”,获取30个源码项目*/ #define HEADER1 " -------------------------------BOOK TICKET----------------------------------\n" #define HEADER2 " |  num
C语言与CPP编程
2020/10/18
2.6K0
C++实现哈夫曼编码压缩软件
一个简单的压缩软件,利用哈夫曼思想,构造哈夫曼编码,实现对文件的二进制压缩,以及解压,再利用MFC制作可视化操作界面,美化软件又简化文件操作。(各个步骤有解释可看)
HcodeBlogger
2020/07/14
2.2K0
C++实现哈夫曼编码压缩软件
哈夫曼树 编码-数据结构(C语言)
  本文使用C语言。对某一输入的字符串,对其构造哈夫曼()树,并由此树的到字符串中每一个字符的哈夫曼编码
宜轩
2022/12/29
5250
[数据结构] 使用最小堆思想实现哈夫曼编解码
假设有n个权值,构造有n个叶子结点的二叉树,每个叶子结点的权值是n个权值之一,这样的二叉树可以构造很多棵,其中必有一棵是带权路径长度最小的,这棵二叉树就称为最优二叉树或哈夫曼树。
泰坦HW
2020/07/22
2.3K0
[数据结构] 使用最小堆思想实现哈夫曼编解码
C语言课程实训:员工信息管理系统
一家公司不仅应该有管理者,还应该有数量更多的普通员工,一个员工信息管理系统,不仅要有管理员操作的模块还要有员工模块。
十二惊惶
2024/02/28
2460
808《数据结构》参考答案
1. 从键盘输入10个整数建立一个顺序表,编程求这10个整数的最大值和次大值并输出。
石璞东
2022/01/18
7020
java算法刷题00——数据结构基础知识回顾
数据、数据元素(如一个账号)、数据项(密码、昵称)、数据结构(具有关系的一组数据元素集合,联想汉字的结构其实就是具有布局关系的符号组合)、数据对象(具有相同性质的数据元素的集合、一家海底捞的排队信息可以看作数据结构、全国所有门店排队信息看做同一个数据对象,它们虽无直接关系,但是具有同样的联系)
半旧518
2022/10/26
2890
【数据结构】建立二叉树以及哈夫曼树及哈夫曼编码
文章目录 5.4.1 方式 5.4.2 由先根和中根遍历序列建二叉树 5.4.3 由后根和中根遍历序列建二叉树 5.4.4 由标明空子树的先根遍历建立二叉树 5.4.5 由完全二叉树的顺序存储结构建立二叉链式存储结构 5.5 哈夫曼树及哈夫曼编码 5.5.1 基本概念 5.5.2 最优二叉树 5.5.3 构建哈夫曼树 5.5.4 哈夫曼编码 5.5.5 哈夫曼编码类 5.4.1 方式 四种方式可以建立二叉树 由先根和中根遍历序列建二叉树 由后根和中根遍历序列建二叉树 由标明空子树的先根遍
陶然同学
2023/02/26
1.1K0
【数据结构】建立二叉树以及哈夫曼树及哈夫曼编码
赫夫曼编译码器的源代码
用户11070251
2024/04/11
1090
数据结构(15)–哈夫曼树以及哈夫曼编码的实现「建议收藏」
大家好,我是架构君,一个会写代码吟诗的架构师。今天说一说数据结构(15)--哈夫曼树以及哈夫曼编码的实现「建议收藏」,希望能够帮助大家进步!!!
Java架构师必看
2022/10/05
2.7K0
数据结构(15)–哈夫曼树以及哈夫曼编码的实现「建议收藏」
数据结构实验C语言实现版
数据结构实验——顺序表的基本操作 /*-----顺序表的基本操作-----*/ #include<stdio.h> #include<stdlib.h> #define maxsize 1024 typedef char elemtype; typedef struct { elemtype list[maxsize]; int length; }sequenlist; void creatlist(sequenlist *L) { int n,i; char tmp; printf("请输入
荣仔_最靓的仔
2021/02/02
9770
【C++实验】哈夫曼树与哈夫曼编码实验
利用哈夫曼编码进行通信可以大大提高信道利用率,缩短信息传输时间,降低传输成本。但是,这要求在发送端通过一个编码系统对待传数据预先编码,在接收端将传来的数据进行译码(复原)。对于双工信道(即可以双向传输信息的信道),每端都需要一个完整的编/译码系统。试为这样的u信息收发编写一个哈夫曼码的编/译码系统。
哈__
2024/06/23
1510
数据结构_二叉树(C++
算法实现: pre、mid:前序遍历、中序遍历的结果结果数组 pl、pr、ml、mr:前序、中序遍历结果数组的左右边界 p:创建当前树的根结点 leftRoot、rightRoot:创建当前树的左子树、右子树的根结点 pos:记录当前树的根在中序遍历中的位置 (根在前序遍历中的位置不用记录,前序遍历结果的第一个就是) num:记录左子树结点的个数 lpl、 lpr、 lml、 lmr:记录前序遍历、中序遍历中左子树的范围 rpl,、rpr,、rml、rmr:记录前序遍历、中序遍历中右子树的范围 ​
用户10551528
2023/05/09
4110
数据结构_二叉树(C++
数据结构 Huffman树
Huffman 介绍 哈夫曼树又称最优二叉树,是一种带权路径长度最短的二叉树。所谓树的带权路径长度,就是树中所有的叶结点的权值乘上其到根结点的路径长度(若根结点为0层,叶结点到根结点的路径长度为叶结点
Kindear
2017/12/29
1.5K0
数据结构 Huffman树
数据结构图文解析之:哈夫曼树与哈夫曼编码详解及C++模板实现
0. 数据结构图文解析系列 数据结构系列文章 数据结构图文解析之:数组、单链表、双链表介绍及C++模板实现 数据结构图文解析之:栈的简介及C++模板实现 数据结构图文解析之:队列详解与C++模板实现 数据结构图文解析之:树的简介及二叉排序树C++模板实现. 数据结构图文解析之:AVL树详解及C++模板实现 数据结构图文解析之:二叉堆详解及C++模板实现 数据结构图文解析之:哈夫曼树与哈夫曼编码详解及C++模板实现 数据结构图文解析之:直接插入排序及其优化(二分插入排序)解析及C++实现 1. 哈夫曼编码简
Tencent JCoder
2018/07/02
1K0
哈夫曼树与哈夫曼编码:聪明的数据压缩技术
👋 你好,我是 Lorin 洛林,一位 Java 后端技术开发者!座右铭:Technology has the power to make the world a better place.
Lorin 洛林
2023/11/14
8561
哈夫曼树与哈夫曼编码:聪明的数据压缩技术
二叉树的应用详解 - 数据结构
1、排序树——特点:所有结点“左小右大 2、平衡树——特点:所有结点左右子树深度差≤1 3、红黑树——特点:除了具备二叉查找树的特性外还有5个特性以致保持自平衡。 4、字典树——由字符串构成的二叉排序树 5、判定树——特点:分支查找树(例如12个球如何只称3次便分出轻重) 6、带权树——特点:路径带权值(例如长度) 7、最优树——是带权路径长度最短的树,又称 Huffman树,用途之一是通信中的压缩编码。
黄规速
2022/04/14
1.4K0
二叉树的应用详解 - 数据结构
哈夫曼编码
1.哈夫曼编码是一种可以被唯一解读的二进制编码 2.前缀编码保证了解码时不会有多种可能 3.哈夫曼编码有不等长和等长两种编码,为了保证不等长编码的唯一性,使用前缀编码 4.频率低的采用短编码,频率高的采用长编码。
大忽悠爱学习
2021/03/18
7480
相关推荐
数据结构之哈夫曼树和编码器的构造
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文