总有能力强的学生, 两个小时就可以完成我当年本科毕业设计的核心代码. 任务描述:

  1. 从文件中读文本;
  2. 统计字符频次, 并建立字母表;
  3. 构造 Huffman 树;
  4. 将文本编码;
  5. 解码.

1. 涂然的版本

分析:

  1. parent, lchild, rchild 都用的是整数, 即下标. 也就是说, 先建立节点, 存放于一个数组 (线性表) 中, 再进行链接. 避免使用指针, 有静态链表的味道, good!

1.1 Huffman.cpp

/*
Descripttion:
Version: 1.0
Author: 涂然 18计科3班
Date: 2021-05-31 9:00:00
*/#include <iostream>
#include <fstream>
#include <string.h>
using namespace std; #define MaxSize 1024  // 读入文件的上限
#define OK 1
#define ERROR 0
typedef int Status;typedef struct wordcnt{  // 统计字符和对应的次数 char ch;int cnt = 0;
}Count;typedef struct NumCount{  // 统计次数的外部封装 Count count[MaxSize];int length = 0;
}NumCount;typedef struct HTree{  // 哈夫曼树结构 char data; int weight;int parent,lchild,rchild;
}HTNode,*HuffmanTree; typedef struct HCode{ // 编码结构 char data;char* str;
}*HuffmanCode;Status ReadData(char *source);  // 读入文件
Status WordCount(char *data,NumCount *paraCnt); // 统计次数
Status Show(NumCount *paraCnt);   // 展示次数
Status CreateHuffmanTree(HuffmanTree &HT,int length,NumCount cntarray);  // 创建哈夫曼树
Status select(HuffmanTree HT,int top,int *s1,int *s2);  // 选择权重最小的两个节点
Status CreateHuffmanCode(HuffmanTree HT,HuffmanCode &HC,int length);  // 创建哈夫曼编码
Status Encode(char *data,HuffmanCode HC,int length);  // 将读入的文件编码,写到txt文件
Status Decode(HuffmanTree HT,int length);  //读入编码文件,解码 int main(int argc, char** argv) {char data[MaxSize];  NumCount Cntarray;ReadData(data);  // 读入数据 WordCount(data,&Cntarray);  // 统计次数
//  Show(&Cntarray); //可以查看每个单词出现的对应次数 HuffmanTree tree;CreateHuffmanTree(tree,Cntarray.length,Cntarray);  // 建树 HuffmanCode code;  CreateHuffmanCode(tree,code,Cntarray.length);  // 创建编码 Encode(data,code,Cntarray.length);  // 生成编码文件 Decode(tree,Cntarray.length);  // 解码 cout<<"Please view the generated TXT file to check the result"<<endl; return 0;
}Status ReadData(char *source)
{//打开文件读入数据 ifstream infile;infile.open("in.txt");cout<<"Reading..."<<endl;cout<<"the input file is:"<<endl;infile.getline(source,MaxSize);cout<<source<<endl;infile.close();cout<<endl;return OK;
}Status WordCount(char *data,NumCount *paraCnt)
{int flag;// 标识是否已经记录 int len = strlen(data);for(int i = 0;i < len;++i){flag = 0;for(int j = 0;j < paraCnt->length;++j){if(paraCnt->count[j].ch == data[i]) // 若已有记录,直接++ {++paraCnt->count[j].cnt;flag = 1;break;}}if(!flag) // 没有记录,则新增 {paraCnt->count[paraCnt->length].ch = data[i];++paraCnt->count[paraCnt->length].cnt;++paraCnt->length;}}return OK;
}Status Show(NumCount *paraCnt)
{cout<<"the length is "<<paraCnt->length<<endl;for(int i = 0;i < paraCnt->length;++i){cout<<"The character "<<paraCnt->count[i].ch<<"  appears  "<<paraCnt->count[i].cnt<<endl;}cout<<endl;return OK;
}Status CreateHuffmanTree(HuffmanTree &HT,int length,NumCount cntarray)
{if(length <= 1) return ERROR;int s1,s2;int m = length*2-1;  // 没有度为1的节点,则总结点是2*叶子节点数-1个 HT = new HTNode[m+1];for(int i = 1;i <= m;++i)  // 初始化 {HT[i].parent = 0;HT[i].lchild = 0;HT[i].rchild = 0;}for(int i = 1;i <= length;++i) {HT[i].data = cntarray.count[i-1].ch;HT[i].weight = cntarray.count[i-1].cnt;}for(int i = length + 1;i <= m;++i){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;  // 得到一个新节点 }return OK;
}Status select(HuffmanTree HT,int top,int *s1,int *s2)
{int min = INT_MAX;for(int i = 1;i <= top;++i)  // 选择没有双亲的节点中,权重最小的节点 {if(HT[i].weight < min && HT[i].parent == 0){min = HT[i].weight;*s1 = i;}}min = INT_MAX;for(int i = 1;i <= top;++i)  // 选择没有双亲的节点中,权重次小的节点 {if(HT[i].weight < min && i != *s1 && HT[i].parent == 0){min = HT[i].weight;*s2 = i;}}return OK;
}Status CreateHuffmanCode(HuffmanTree HT,HuffmanCode &HC,int length)
{HC = new HCode[length+1];char *cd = new char[length];  // 存储编码的临时空间 cd[length-1] = '\0';  // 方便之后调用strcpy函数 int c,f,start;for(int i = 1;i <= length;++i){start = length-1;  // start表示编码在临时空间内的起始下标,由于是从叶子节点回溯,所以是从最后开始 c = i;f = HT[c].parent;while(f != 0){--start;  // 由于是回溯,所以从临时空间的最后往回计 if(HT[f].lchild == c)cd[start] = '0';else cd[start] = '1';c = f;f = HT[c].parent;}HC[i].str = new char[length-start];  // 最后,实际使用的编码空间大小是length-start HC[i].data = HT[i].data;strcpy(HC[i].str,&cd[start]);  // 从实际起始地址开始,拷贝到编码结构中 }delete cd;
}Status Encode(char *data,HuffmanCode HC,int length)
{ofstream outfile;outfile.open("code.txt");for(int i = 0;i < strlen(data);++i)  // 依次读入数据,查找对应的编码,写入编码文件 {for(int j = 1;j <= length;++j){if(data[i] == HC[j].data){outfile<<HC[j].str;}}}outfile.close();cout<<"the code txt has been written"<<endl;cout<<endl;return OK;
}Status Decode(HuffmanTree HT,int length)
{char codetxt[MaxSize*length];ifstream infile;infile.open("code.txt");infile.getline(codetxt,MaxSize*length);infile.close();ofstream outfile;outfile.open("out.txt");int root = 2*length-1;  // 从根节点开始遍历 for(int i = 0;i < strlen(codetxt);++i){if(codetxt[i] == '0') root = HT[root].lchild;  //为0表示向左遍历 else if(codetxt[i] == '1') root = HT[root].rchild; //为1表示向右遍历 if(HT[root].lchild == 0 && HT[root].rchild == 0)  // 如果已经是叶子节点,输出到输出文件中,然后重新回到根节点 {outfile<<HT[root].data;root = 2*length-1;}}outfile.close();cout<<"the output txt has been written"<<endl;cout<<endl;return OK;
}

1.2 附文本文件内容

in.txt

Life is full of confusing and disordering Particular time,a particular location,Do the arranged thing of ten million time in the brain,Step by step ,the life is hard to avoid delicacy and stiffness No enthusiasm forever,No unexpected happening of surprising and pleasing So,only silently ask myself in mind Next happiness,when will come?

2. 刘雄的版本

  1. source.txt 这么短, 怎么编码

    数据结构 C 代码 6.2: 哈夫曼树 (学生提供代码)相关推荐

    1. 数据结构图文解析之:哈夫曼树与哈夫曼编码详解及C++模板实现

      0. 数据结构图文解析系列 数据结构系列文章 数据结构图文解析之:数组.单链表.双链表介绍及C++模板实现 数据结构图文解析之:栈的简介及C++模板实现 数据结构图文解析之:队列详解与C++模板实现 ...

    2. 哈夫曼树构造以及代码实现

      哈夫曼树构造以及代码实现 什么是哈夫曼树 理解哈夫曼树 哈夫曼树的构造 哈夫曼树构造-代码实现 什么是哈夫曼树 构造一颗二叉树,该树的带权路径长度达到最小,称为最优二叉树,也称为哈夫曼树(Huffma ...

    3. 【数据结构与算法基础】哈夫曼树与哈夫曼编码(C++)

      前言 数据结构,一门数据处理的艺术,精巧的结构在一个又一个算法下发挥着他们无与伦比的高效和精密之美,在为信息技术打下坚实地基的同时,也令无数开发者和探索者为之着迷. 也因如此,它作为博主大二上学期最重 ...

    4. 【数据结构】基于c++的哈夫曼树构造、编码、译码算法实现

      创建哈夫曼树的描述: 数据结构: 数据的逻辑结构是树状结构:采用静态的三叉链表存放. 算法思想: 1.先把三叉链表中N个元素进行初始化,存放叶子节点,他们都没有孩子和双亲. 2.再初始化后n-1个非叶 ...

    5. 常用数据结构之线索二叉树和哈夫曼树

      1.线索二叉树 上一篇二叉树中,我们介绍了基本的二叉树的结构.每一个父节点对应两个子节点,左子节点和右子节点.其中我们会看到,很多节点的左右节点都为null,为了更高效的存储和遍历,我们考虑一种方式将 ...

    6. 【数据结构和算法笔记】哈夫曼树的概念,构造和应用(利用哈夫曼编码压缩文本)

      目录 哈夫曼树定义: 构造哈夫曼树: 哈夫曼编码 前缀编码: 应用(压缩文本) 哈夫曼树定义: 构造哈夫曼树: 哈夫曼编码 前缀编码:  哈夫曼编码是前缀编码 哈夫曼树的性质 哈夫曼树的任意非叶结点的 ...

    7. 数据结构“基于哈夫曼树的数据压缩算法”的实验报告

      一个不知名大学生,江湖人称菜狗 original author: jacky Li Email : 3435673055@qq.com Last edited: 2022.11.20 目录 数据结构& ...

    8. c语言霍夫曼函数,使用C语言详解霍夫曼树数据结构

      1.基本概念 a.路径和路径长度 若在一棵树中存在着一个结点序列 k1,k2,--,kj, 使得 ki是ki+1 的双亲(1<=i 从 k1 到 kj 所经过的分支数称为这两点之间的路径长度,它 ...

    9. 【Java数据结构】赫夫曼树

      哈弗曼树 哈弗曼树定义 哈弗曼树示例 哈弗曼树代码实现 哈弗曼树定义 给定 N 个权值作为 N 个叶子结点,构造一棵二叉树,若该树的带权路径长度(WPL)达到最小,称这样的二叉树为最优二叉树,也称为哈 ...

    最新文章

    1. 反转字符串/列表、改变递归次数限制、else用法...Python 冷知识(四)
    2. python 分词包_NLP相关python包
    3. react 逆地理 高德地图_在react中使用原生的高德地图
    4. 服务器io修改,更改 Linux I/O 调度器来改善服务器性能
    5. jboss fuse 教程_在JBoss Fuse / Fabric8 / Karaf中使用Byteman
    6. 图谱问答-理解query
    7. 【数字逻辑设计】Logisim构建三种多路选择器
    8. 我的docker随笔5:docker-compose的安装与使用
    9. 对象存储 OSS > 开发指南 > 存储类型 > 存储类型介绍
    10. Windows2003 安装MVC4 环境的步骤
    11. C++ string append方法的常用用法
    12. 黑马程序员视频-微信小程序-原生框架——项目搭建
    13. 决策树ID3算法实现与讨论(完整代码与数据)
    14. 全国最大SLAM开发者学习交流社区 欢迎加入
    15. 用数组统计学生各个分数段成绩的人数
    16. 晶振电路的PCB设计
    17. 云栖大会人脸识别闸机【技术亮点篇4】--户外闸机高20%的抗撞击能力
    18. sql server 添加表注释、字段注释
    19. Storm(三):Storm入门Demo
    20. 十二、Redis LRU算法详述(Least Recently Used - 最近最少使用)

    热门文章

    1. Matlab绘制ROC曲线并计算AUC面积
    2. IO流-(File)
    3. 一些实用的cmd命令,让你变得很牛X
    4. 神经网络应用现状分析,神经网络应用现状调查
    5. OpenCV小案例——批量图片合成为视频
    6. scada与MySQL连接_SCADA系统关系数据库转储
    7. 如何解决Windows10启动QQ时报错无法访问个人文件夹?
    8. Android 学习论坛博客及网站推荐
    9. Fedora安装字体方法和Ubuntu非常不同!
    10. call和calling的用法_英语词汇call的短语及用法