哈夫曼编码-译码器的设计与实现 (数据结构课设)

数据结构课程设计。用的C++写的。

一、问题描述

打开一篇英文文章,统计该文章中每个字符出现的次数,然后以它们作为权值,对每一个字符进行编码,编码完成后再对其编码进行译码。

利用哈夫曼编码进行信息通信可以大大提高信道利用率,缩短信息传输时间,降低传输成本。但是,这要求在发送端通过一个编码系统对待传数据预先编码,在接收端将传来的数据进行译码(复原)。对于双工信道(即可以双向传输信息的信道),每端都需要一个完整的编/译码系统。试为这样的信息收发站写一个哈夫曼编/译码系统。

测试数据(ToBeTran.txt)

Next morningthey met at breakfast. All three were somewhat silent. It was as if the weightof the matter which was that day to be discussed pressed upon their spirits.The smallest of the trio, Septimus Codd by name, who was habitually taciturn,spoke scarcely a word. He was a strange little man, a nineteenth centuryvillain in a sense. He was a rogue and a vagabond, yet his one hobby, apartfrom his business, was a study of the Past, and many an authority on EasternHistory would have been astonished at the extent of his learning. He was neverso happy as when burrowing amongst ancient records, and it was mainly due tohis learning in the first place, and to a somewhat singular accident in thesecond, that the trio were now foregathered in Singapore. His personalappearance was a peculiar one. His height was scarcely more than four feet sixinches. His face was round, and at a distance appeared almost boyish. It wasonly when one came to look into it more closely, that it was seen to be scoredby numberless small lines. Moreover it was unadorned by either beard ormoustache. His hair was grey, and was worn somewhat longer than is usual. Hecould speak fluently almost every language of the East, and had been imprisonedby the Russians for sealing in prohibited waters, had been tortured by theChinese on the Yang-tse, and, to his own unextinguishable disgrace, flogged bythe French in Tonquin. Not the least curious trait in his character was theaffection he entertained for Kitwater. The pair had been together for years,had quarrelled repeatedly, but had never separated. The record of their doingswould form an interesting book, but for want of space cannot be more thanreferred to here. Hayle had been their partner in not a few of their curiousundertakings, for his courage and resource made him a valuable ally, though howfar they trusted each other it is impossible to say.

三、数据与结构说明

1.typedef struct

{

char ch;//出现的各字符种类

char bits[15];//各字母的码字

int len;

}CodeNode;

typedef CodeNode HuffmanCode[256];//结构体数组表示译码部分数据

2.typedef struct

{

//数据成员

int weight;//权数据域

int parent, lchild,rchild;//双亲,左右孩子域

char key;

}HufNode ;

typedef HufNode nodes[256];// 用结构体数组表示编码部分数据

3. void Getfrequen(int d[256], int& n,char page[])//字符统计函数

4. void Getfrequen(int d[256], int& n,char page[])//字符统计函数

5. void starttree(nodes& HT,int& n)//哈夫曼树初始化

6. void select(nodes HT,int k, int& r1, int& r2)//挑选最小的和次小的二叉树

7. void Savefile(nodes& HT, HuffmanCode& HC)//保存文件

8. void HufTree(nodes& HT, HuffmanCode& HC, int d[256], char str[],char page[])//哈夫曼树建立

9. void encode(nodes& HT, HuffmanCode& HC)//对各字符进行哈夫曼编码

10. void coding(nodes& HT, HuffmanCode& HC, char st[], char get[])//对文本正文进行编码

11. void decode(HuffmanCode& HC, char code[],char result[])//译码

12. void Cout(char code[], int& c)//读取需译码的文件并统计文件码字数

四、运行截图

(1)初始化(Initialization)。从文件ToBeTran.txt中读入英文字符集,统计字符出现次数,作为权值建立哈夫曼树,获得哈夫曼编码,并存放于文件hfmCode.txt中。

ToBeTran.txt如下图

哈夫曼编码-译码器的设计与实现 (数据结构课设)_第1张图片

hfmCode.txt

哈夫曼编码-译码器的设计与实现 (数据结构课设)_第2张图片

(2)编码(Encoding)。利用已建好的哈夫曼编码,对文件ToBeTran.txt中的正文进行编码,然后将编码后的结果存入文件CodeFile.txt中。

CodeFile.txt如图

哈夫曼编码-译码器的设计与实现 (数据结构课设)_第3张图片

(3)译码(Decoding)。利用哈夫曼编码将文件CodeFile.txt中的代码进行译码,结果存入文件TextFile.txt中。

TextFile.txt如图

哈夫曼编码-译码器的设计与实现 (数据结构课设)_第4张图片

源码:

PS:文件路径自己修改,本人用的VS2022运行是没问题的

#define _CRT_SECURE_NO_WARNINGS
#include
#include
#include 
#include 
#include 
using namespace std;

int n;//字符种类个数
typedef struct
{
    char ch;//出现的各字符种类
    char bits[15];//各字母的码字
    int len;
}CodeNode;
typedef CodeNode HuffmanCode[256];

typedef struct 
{
    //数据成员
    int weight;//权数据域
    int parent, lchild, rchild;//双亲,左右孩子域
    char key;
}HufNode ;
typedef HufNode nodes[256];//用结构体数组表示编码部分数据

void Getfrequen(int d[256], int& n,char page[])//字符统计函数
{
    int p = 0;
    ifstream binafile("d://杀鸡结构//ToBeTran.txt", ios::binary);
    n = 0; 
    while (!binafile.eof())//遍历文件,读取文本文件内容,存至类哈希数组中
    {
        unsigned int temp = binafile.get();
        if (temp > 128)break;
        if (d[temp] == 0)
        {
            d[temp] = 1; n++;
        }
        else d[temp]++;
        page[p] = temp;p++; 
    }
    binafile.close();
}

void starttree(nodes& HT,int& n)//哈夫曼树初始化
{
   for (int i = 0; i < 2 * n - 1; i++)
    {
        HT[i].lchild = -1;
        HT[i].rchild = -1;
        HT[i].parent = -1;
        HT[i].weight = -1;
    }
}

void select(nodes HT,int k, int& r1, int& r2)//挑选最小的和次小的二叉树
{
    r1 = r2 = -1;
    for (int i = 0; i < k; i++)        //查找树值最小
    {
        if (HT[i].parent == -1)     //只处理根节点
            if (r1 == -1)
                r1 = i;
            else if (HT[i].weight < HT[r1].weight)
            {
                r2 = r1; r1 = i;
            }
            else if (r2 == -1 || HT[i].weight < HT[r2].weight)
                r2 = i;
    }
}

void Savefile(nodes& HT, HuffmanCode& HC)//保存文件
{
    ofstream savefile2;
    savefile2.open("d://杀鸡结构//hfmCode.txt");
    if (!savefile2) {
        cerr << "CodeFile.txt文件打开失败" << endl;
        exit(1);
    }
    for(int h=0;h0)
   {
      ifstream binafile("d://杀鸡结构//ToBeTran.txt", ios::binary);
      while (!binafile.eof())//遍历文件
      {
         unsigned int temp= binafile.get(); 
          if (d[temp] <= 0)continue;
          w = *max_element(d, d + 256);
          if (d[temp] == w)//对结点的权值进行赋值
          {
              HT[num - 1].weight = w;
              HT[num - 1].key = temp;
              str[num - 1] = temp;
              d[temp] = 0; num--; break;
          }
      }
      binafile.close();
    }
    for (i = n ; i < 2 * n - 1; i++)
    {
        select(HT,i, s1, s2);//选出最小的两个结点(结点位置存放在s1、s2中)
        //往HT序列后一位i放置新生成的父亲结点
        HT[s1].parent = i;//s1结点的父结点为i结点
        HT[s2].parent = i;//s2结点的父结点为i结点
        HT[i].lchild = s1;//父结点的左孩子结点为s1结点
        HT[i].rchild = s2;//父结点的右孩子结点为s2结点
        HT[i].weight = HT[s1].weight + HT[s2].weight;//计算父结点的权值
    }
    for (i = 0; i < n; i++)//初始化哈夫曼编码
    {
        HC[i].ch = str[i];
    }
}

void encode(nodes& HT, HuffmanCode& HC)//对各字符进行哈夫曼编码
{
    int c, p, i; 
    char cd[256] = {};//记录当前编码
    int start;//记录编码起始位置(结尾位置为n)
    cd[n] = '\0';//设置编码结尾位置
    for (i = 0; i < n; i++)
    {
        start = n-1;
        c = i;
        while ((p = HT[c].parent) > 0)//倒序编码
        {
            start--;
            cd[start] = (HT[p].lchild == c) ? '0' : '1';
            c = p;
        }
        strcpy(HC[i].bits, &cd[start]);
        HC[i].len = n - start;
    }
}

void coding(nodes& HT, HuffmanCode& HC, char  st[], char get[])//对文本正文进行编码
{
    int i, j = 0,length=0;
    while (st[j] != '\0')//根据文本的字符顺序,用字符和哈夫曼编码进行编码
    {
        for (i = 0; i < n; i++)
        {
            if (HC[i].ch == st[j])
            {
                strcat(get, HC[i].bits);
                length += HC[i].len;
                break;
            }
        }
        j++;
    }
    strcat(get, "\0");
    ofstream savefile;
    savefile.open("d://杀鸡结构//CodeFile.txt", ios::binary);
    if (!savefile) {
        cerr << "CodeFile.txt文件打开失败" << endl;
        exit(1);
    }
    savefile<

你可能感兴趣的:(课程设计,数据结构,c++)