哈夫曼树的编码解码,输入是一个txt文件吗,给出文件的路径;

里面包含的结构体声明如下:

#define NOTFIND -1
#define LEFT    0
#define RIGHT 1struct h_code{                      //哈夫曼编码的结构体char data;vector<string>char_code;       //存放字符的哈夫曼编码的
};struct node
{int count;        //字符出现的次数char data;        //保存字符struct node* pleftchild;      //右孩子struct node* prightchild;     //左孩子int level;                    //表示节点的所在层数
};bool operator <(node a,node b){     //给结构体设置优先队列return a.count>b.count;
}

类的声明如下:

class Huffman_code{
private:string filepath = R"(C:\Users\ycig\CLionProjects\haffman_code\data.txt)";char nochar = '#';      //非叶子节点的数据域保存的数据node *p;                //哈夫曼树的工作指针node phead;             //哈弗曼树头结点h_code *p_h_code;        //哈夫曼编码结构体数组的首地址int char_size;          //读取的字符的种类个数vector<char>chartxt;    //存放文本的数据int Find_char(char input);      //寻找字符在哈夫曼编码结构体数组的位置
public:Huffman_code();    //构造函数void char_code();      //打印哈夫曼树,生成哈夫曼编码void huffman_encode();      //对文本进行编码,并写入txt文档void huffman_decode();      //哈夫曼解码void Show_char_code();      //打印哈夫曼字符编码void Level_traversal(node * q,int level);     //哈夫曼树的层次遍历,标记每一层节点所在的层数
};

大概流程是:

读取txt文件:

ifstream in(filepath);  //打开文件,filepath的值是类的私有属性in>>noskipws;          //不跳过换行和空格char ch;                vector<char>words;    //接收读取的txt的字符数组struct node *work_node = new struct node;while(in>>ch)   //加入字符数组{words.push_back(ch);}

统计字符出现的次数:

 vector<struct node>my_char;               //存放字符出现次数的for(int i=0;i<words.size();i++){if(have_char(my_char,words[i]) == NOTFIND)        //字符还没有统计{work_node->count = 1;          //出现次数设置为1work_node->data = words[i];          //记录字符串work_node->pleftchild = nullptr;     //左孩子置为空work_node->prightchild = nullptr;    //右孩子置为空my_char.push_back(work_node[0]);}

将统计好次数的结构体数组放到优先队列里面去,哈夫曼树的构造选取的是贪心算法,每次取权重最小的两棵树,生成一颗新的树,然后放到优先队列里面去;循环的终止条件是优先队列里面只有一个树,也就是下面的node_priqueue.size() == 1的时候。

 while(node_priqueue.size()>1){node * left = new node ;            //左孩子节点node * right = new node;            //右孩子节点node * father = new node;           //父节点left->pleftchild = node_priqueue.top().pleftchild;      //接收优先队列队首的值left->prightchild = node_priqueue.top().prightchild;left->data = node_priqueue.top().data;left->count = node_priqueue.top().count;node_priqueue.pop();                                //出队right->data = node_priqueue.top().data;right->count = node_priqueue.top().count;right->prightchild = node_priqueue.top().prightchild;right->pleftchild = node_priqueue.top().pleftchild;node_priqueue.pop();father->pleftchild = left;                     //把左右孩子连接到父节点去father->prightchild = right;father->count = left->count+right->count;father->data = nochar;                         //父节点的字符域设为默认值node_priqueue.push(*father);                    //父节点进队}

生成之后初始化了些东西,如下:

  phead = node_priqueue.top();p = &phead;                    //保存哈夫曼树的指针chartxt = words;                //保存读取到的数据,后面生成编码会用到//*************设置哈夫曼树节点的层数**********************************Level_traversal(&phead);        //给生成哈夫曼树的节点标记下层数,递归写的,生成哈夫曼字符编码会用到

下面开始遍历哈夫曼树,生成字符编码。

我的思路是用栈保存指针移动的轨迹,从头节点开始,如果向左移动,就往压栈0(0表示向左移动,1表示向右移动)。

先序遍历,当p第一次移动到空的时候:

节点栈里面的有:9,4,2,A

轨迹栈:0000

此时指针移动到A的左孩子,此时为空,然后弹节点栈,得到A的指针,判断节点A在多少层,A在第三层,轨迹栈只能有(A->level-1)3个元素,出栈一个元素;此时:

节点栈:9,4,2

轨迹栈:000

指针移动到A的右孩子,也为空,继续弹栈,得到2号节点,在第三层,轨迹栈只能有3-1个元素。

此时:

节点栈:9,4

轨迹栈:00

指针移动到2号节点的右孩子,到B位置,轨迹栈压栈1,此时

节点栈:9,4,B

轨迹栈:001

输出轨迹栈,用一个栈保存节点栈的数据,往新的栈里面压栈,然后再弹出就可以得到100的编码

指针继续移动到B的左孩子,B的左孩子为空,弹节点栈得到B号节点,判断节点B在多少层,B在第三层,轨迹栈只能有(B->level-1)3个元素,不出栈

此时:

节点栈:9,4

轨迹栈:001

B的右孩子也为空,将p空置,继续弹节点栈得到节点4,在第二层,轨迹栈最多1个元素,出轨迹栈两次

此时:

节点栈:9

轨迹栈:0

指针继续移动到第二个二号节点,压轨迹栈1。此时:

节点栈:9,2

轨迹栈:01

继续左移,到C节点,此时:

节点栈:9,2,c:

轨迹栈:010

记录C的哈夫曼编码。继续移动到C的孩子,为空,不压轨迹栈。

弹节点栈,弹栈得到第二个2号节点(9),在第三层,轨迹栈只能有2个元素,出栈一次(01)。移动到D号节点,轨迹栈压栈一次1,此时:

节点栈:9,D

轨迹栈:011

记录D的哈夫曼编码

D无左右孩子,弹栈得到9号节点(根节点),轨迹栈最多只能有(1-1)个元素,弹空。

以上就是左子树遍历的过程。有了哈夫曼编码,解码就容易多了。

下面就是全部代码:

#include <iostream>
#include "fstream"
#include "string"
#include<vector>
#include "queue"
#include "stack"
using namespace std;#define NOTFIND -1
#define LEFT    0
#define RIGHT 1struct h_code{                      //哈夫曼编码的结构体char data;vector<string>char_code;       //存放字符的哈夫曼编码的
};struct node
{int count;        //字符出现的次数char data;        //保存字符struct node* pleftchild;      //右孩子struct node* prightchild;     //左孩子int level;
};bool operator <(node a,node b){     //给结构体设置优先队列return a.count>b.count;
}class Huffman_code{
private:string filepath = R"(C:\Users\ycig\CLionProjects\haffman_code\data.txt)";char nochar = '#';      //非叶子节点的数据域保存的数据node *p;                //哈夫曼树的工作指针node phead;             //哈弗曼树头结点h_code *p_h_code;        //哈夫曼编码结构体数组的首地址int char_size;          //读取的字符的种类个数vector<char>chartxt;    //存放文本的数据int Find_char(char input);      //寻找字符在哈夫曼编码结构体数组的位置
public:Huffman_code();    //构造函数void char_code();      //打印哈夫曼树,生成哈夫曼编码void huffman_encode();      //对文本进行编码,并写入txt文档void huffman_decode();      //哈夫曼解码void Show_char_code();      //打印哈夫曼字符编码void Level_traversal(node * q,int level);     //哈夫曼树的层次遍历,标记每一层节点所在的层数
};void Huffman_code::Level_traversal(node * q,int level=1) {if(q){q->level = level;if(q->pleftchild){Level_traversal(q->pleftchild,level+1);}if(q->prightchild){Level_traversal(q->prightchild,level+1);}}
}void Huffman_code::Show_char_code() {for(int i=0;i<char_size;i++){cout<<p_h_code[i].data<<"的哈夫曼编码是: ";for(int j=0;j<p_h_code[i].char_code.size();j++){cout<<p_h_code[i].char_code[j];}cout<<endl;}
}void Huffman_code::huffman_decode() {ifstream in(R"(..\Huffmancode.txt)");queue<char>decode_queue;char ch;while(in>>ch){decode_queue.push(ch);}p = &phead;//清空文件内容ofstream out(R"(..\Huffmandecode.txt)",ios::trunc);while(p&&!decode_queue.empty()){while(p->data == nochar){if(decode_queue.front() == '1'){p = p->prightchild;decode_queue.pop();}else{p = p->pleftchild;decode_queue.pop();}}//写入文本ofstream out(R"(..\huffmandecode.txt)",ios::app);{out<<p->data;}p = &phead;     //读取到数据后指针重新回到头结点}
}int Huffman_code::Find_char(char input) {for(int i=0;i<char_size;i++){if(p_h_code[i].data == input){return i;}}return NOTFIND;
}void Huffman_code::huffman_encode() {           //将生成的哈夫曼编码写入txt文件vector<string> huffman_encode;           //存放编码的数组for (int i = 0; i < chartxt.size(); i++){int pos = Find_char(chartxt[i]);for(int j=0;j<p_h_code[pos].char_code.size();j++){huffman_encode.push_back(p_h_code[pos].char_code[j]);}}//清空文件内容ofstream in (R"(..\Huffmancode.txt)",ios::trunc);//写入ofstream out(R"(..\Huffmancode.txt)");for(int i=0;i<huffman_encode.size();i++){out<<huffman_encode[i];}
}
int have_char(vector<struct node>my_char,char ch){           //判断字符在不在结构体数组里面for(int i=0;i<my_char.size();i++){if(ch == my_char[i].data){return i;               //找到了就返回下标}}return NOTFIND;                 //没有找到就返回-1
}void Huffman_code::char_code() {h_code *pnew = new h_code[char_size];       //申请空间p_h_code = pnew;                          //赋值给类的私有成员属性int charcode_pos = 0;                     //哈夫曼字符编码的下标p = &phead;                             //取哈夫曼树父节点地址stack<string>huffman_trailed;        //保存哈夫曼编码010101010类型的stack<node *>huffman_stack;       //用来先序遍历保存节点的栈while(!huffman_stack.empty()||p)    //当栈不为空在的时候,执行循环{while(p){if(p->data != '#'){      //当是叶子节点的时候//cout<<"测试编码"<<p->data;p_h_code[charcode_pos].data = p->data;//****************栈的逆序输出(先输出栈底)***************************************stack<string>show;stack<string>copy=huffman_trailed;while(!copy.empty()){show.push(copy.top());copy.pop();}while(!show.empty()){p_h_code[charcode_pos].char_code.push_back(show.top());//cout<<show.top();show.pop();}//cout<<endl;charcode_pos++;              //下标加一}huffman_stack.push(p);              //头结点进栈if(p->pleftchild){p = p->pleftchild;huffman_trailed.push("0");}else{p = nullptr;}}if(!huffman_stack.empty()){             //此时左孩子已经遍历结束p = huffman_stack.top();while(huffman_trailed.size()>p->level-1){huffman_trailed.pop();}huffman_stack.pop();if(p->prightchild){p = p->prightchild;huffman_trailed.push("1");}else{p = nullptr;}}}
}Huffman_code::Huffman_code() {ifstream in(filepath);  //打开文件in>>noskipws;          //不跳过换行和空格char ch;vector<char>words;struct node *work_node = new struct node;while(in>>ch)   //加入字符数组{words.push_back(ch);}//**********************统计字符出现的次数**************************vector<struct node>my_char;               //存放字符出现次数的for(int i=0;i<words.size();i++){if(have_char(my_char,words[i]) == NOTFIND)        //字符还没有统计{work_node->count = 1;          //出现次数设置为1work_node->data = words[i];          //记录字符串work_node->pleftchild = nullptr;     //左孩子置为空work_node->prightchild = nullptr;    //右孩子置为空my_char.push_back(work_node[0]);}else{my_char[have_char(my_char,words[i])].count++;    //字符统计次数加一}}char_size = my_char.size();//****************把统计结果添加到结构体优先队列中*****************priority_queue<node>node_priqueue;for(int i=0;i<my_char.size();i++){node_priqueue.push(my_char[i]);}//***************生成哈夫曼树*************************************while(node_priqueue.size()>1){node * left = new node ;            //左孩子节点node * right = new node;            //右孩子节点node * father = new node;           //父节点left->pleftchild = node_priqueue.top().pleftchild;      //接收优先队列队首的值left->prightchild = node_priqueue.top().prightchild;left->data = node_priqueue.top().data;left->count = node_priqueue.top().count;node_priqueue.pop();                                //出队right->data = node_priqueue.top().data;right->count = node_priqueue.top().count;right->prightchild = node_priqueue.top().prightchild;right->pleftchild = node_priqueue.top().pleftchild;node_priqueue.pop();father->pleftchild = left;                     //把左右孩子连接到父节点去father->prightchild = right;father->count = left->count+right->count;father->data = nochar;                         //父节点的字符域设为默认值node_priqueue.push(*father);                    //父节点进队}phead = node_priqueue.top();p = &phead;chartxt = words;//*************设置哈夫曼树节点的层数**********************************Level_traversal(&phead);//************生成哈夫曼字符编码***************************************char_code();//**************编码*************************************************huffman_encode();
}int main() {Huffman_code().huffman_decode();
}

生成编码文件和解码文件在执行文件.exe的上层目录。

运行效果如下:

输入:

春江花月夜
【作者】张若虚 【朝代】唐译文对照
春江潮水连海平,海上明月共潮生。滟滟随波千万里,何处春江无月明!江流宛转绕芳甸,月照花林皆似霰;空里流霜不觉飞,汀上白沙看不见。江天一色无纤尘,皎皎空中孤月轮。江畔何人初见月?江月何年初照人?人生代代无穷已,江月年年望相似。不知江月待何人,但见长江送流水。白云一片去悠悠,青枫浦上不胜愁。谁家今夜扁舟子?何处相思明月楼?可怜楼上月裴回,应照离人妆镜台。玉户帘中卷不去,捣衣砧上拂还来。此时相望不相闻,愿逐月华流照君。鸿雁长飞光不度,鱼龙潜跃水成文。昨夜闲潭梦落花,可怜春半不还家。江水流春去欲尽,江潭落月复西斜。斜月沉沉藏海雾,碣石潇湘无限路。不知乘月几人归,落月摇情满江树。

编码:

01010001100110001011011000111100000000111101100101010111110100011111000101011101011001001110000010111001111111010110000011101101110110010011100010100000110010111100110000111011101001100100000010101111011111110111000110010011100000100101010100110111110001101010110011100100111000101000001001101000001010000110011010010100010101100011100001000111001101011111010100110111011101001101001010001100110001011011000111010111111001011101010111111001100100001001101001011001010111101100111000101111101011000000000100101100010101011110110011111100011000000110101000111110110010101011111010001110111011011001011111100101111010000110100011111001001110101101110101101001001101000111010011010001111111101110111111011110010101100000010010100011000101001111011100011001100001111110110000111000100000100101100011110011111111101010001111100010011111010100011001100010110110001110101100000111100101010101111101010100011111011000000100100111101101011010010110110001110101011110011110000100101110010001000011111101101110110100011010111010110000000011101100001010000110100110000000100101100010101010111110110100110111011101001000000001111011001000101101100000101001110111100100100111001001010010111110101011011111000001001000100011010110101010001101111101110111110110000111000101010111100111101111101010110101111000110010001010000111010010011101111101011001001011000000100101100010101101100111011100011000000111010000101011111110100110110001010110100101011110111011110001100100010100001110100011110110010011101011011101011010010110110001110001111100001101111111000110001110100001001110011011001011000001111001101001011101111000000110111111000110000010010110001101001110111111101101010011101111111011010100011011111011101110001100011111100010111111111100001010101111101100001111110010111110010011101011011101011010010110110001111010011101010011010111001111111110101111001011101011100001111101001101110000111010001111001010101111101000001001000111010110110001110101010111110111100111111111010100010111110100110000011111010011011101001101110111010011100101110101110000001001000111110101101011100101110101110101000011010001111110001101010110011110001101010110010101100000111100110100011011111100111000111001110110110000001001011000101011011000111010101011111010001011111010011000001011111010011000101010100100010100001000011001110010010100101100100111010110111010110101110001100100010101000011100110001011011000111010101011111010001001001101101110111001111111110101111001011101011100000010010110001111001111110010010010000111010001111011111011101011001101010110110001111111100111001111001010111100111100101011111100110011001001110101101110101101010100001010111111111100101110001010011100011000111010100100111011000010001111011001101001010110111110010101011011111001000001001011000111111000110111100110000100010110111011100101010111101101111111100011000000111110001100100010100001001111010101010100111110111101100100111010110111010110101000010111110111100001001011100100111111000110100000110001111100010101010100111001111010000111101001110001011111100001000000100100011111100111111111010100011111000100111111010000100001100010011100011011010100011111011001010101111101010001100100100000010010001111101011010000111011110110011010100111010101010001100100101110001100000011010101011111011000010110011001100000100100000101100000010010110001000110111000110101010011011101110100101001101111101101011100101110101110000111011111001001001111101110101101010001110111101011111110010011101011011101011010101001110110100111001011110111001110001011001000111110001100011111100011000101100111111000110010001000011110110011010000001001011000101010001010110011000011001100110110011010011110011110100111000110000001101011101110110110110000100110110001101000110110011001100100111010110111010110100100111111111100001011000000010011110100001000011000101010100100011100011001000101010000100001100111110110000001101000000100101100010101001111110011011111100111000001001010101111101000110001011101100101011110011110101001101110111010000010000100010001100100111010110111010110101111100110010011011111100010000111101111101110101100110111111010110010010110000111011101001110111000110010001000011011101101111100000100101100011111101101101001011111000100110001010101011111110101100001100111100111100101011111100110001011110100001001010110001110000111001001110101101110101101001010001101101110000011111000101011111101100000011011001011111101111110100010010111011111100000000101111111000000001111011000000100101100010001110111101100110101001110101010101000110011000001100010000011111000110010001010000100110110001100010010111001001111100100111010110111010110100101101100011101010111111001100010101111001111001010001100110000011110110011010010011011101011011000011011111111111000001001011000101011011000111010111111011111110000000010111111010101011111010001111100010001010000001100100110101010110001101011100100111010110111010110100101011000110101010101011111010100110110100111001001101101001110100001100000110111100101011110110011111111000100000100110000001001011000110100001001011011001101000011110110000010111111110000101001111101000110101100000111100111111000101010000101000011001111100110111001001110101101110101101011100011001000101010000111001100111000111110100011010101011111010001110000111110011110010111010111000011111111100110000000010010110001100000000101111110101010111110101000101001100001010100111101101110010011010110011001010110110001110101111001001010011001001110101101

解码就不展示了,和输入的一模一样。

链表哈夫曼树--编码--解码相关推荐

  1. 基于JavaGUI的哈夫曼树编码解码

    资源下载地址:https://download.csdn.net/download/sheziqiong/85640300 资源下载地址:https://download.csdn.net/downl ...

  2. java哈夫曼树编码_哈夫曼树的编码实验

    Java哈夫曼编码实验--哈夫曼树的建立,编码与解码 建树,造树,编码,解码 一.哈夫曼树编码介绍 1.哈夫曼树: (1)定义:假设有n个权值{w1, w2, ..., wn},试构造一棵含有n个叶子 ...

  3. 赫夫曼树编码的算法及应用习题--数据结构

    赫夫曼树编码的算法及应用习题 1.构造赫夫曼树的方法 1.根据给定的n个权值{w1,w2,---wn},构成n棵二叉树的集合F={T1,T2...,Tn},其中每棵二叉树中只有一个带权为Wi的根结点, ...

  4. 哈夫曼树的构建及哈夫曼树编码

    哈夫曼树的构建: 注意:(1).首先把一组数3 5 6 8 9 12 15从小到大排列 (2).选取里面最小2个,顶点出为2个数的和 (3).新产生的顶点在与原先的数字进行比较,在里面选取2个最小的数 ...

  5. labview 霍夫曼树_哈夫曼树编码实验报告_信息论与编码实验2 实验报告_信息论与编码报告...

    huffman编码C语言实验报告 今日推荐 180份文档 2014...4页 1下载券 安卓版100 doors 2攻略1... 3页 1下载券 <逃脱本色>doors....语文教育实习 ...

  6. 哈夫曼树的创建和哈夫曼树编码及解码

    #define _CRT_SECURE_NO_WARNINGS #include<stdio.h> #include<stdlib.h> #include<string. ...

  7. 哈夫曼树和哈夫曼树编码

    在一般的数据结构的书中,树的那章后面,著者一般都会介绍一下哈夫曼(HUFFMAN) 树和哈夫曼编码.哈夫曼编码是哈夫曼树的一个应用.哈夫曼编码应用广泛,如 JPEG中就应用了哈夫曼编码. 首先介绍什么 ...

  8. 哈夫曼树编码与译码(完整C/C++实现代码)

    哈夫曼编码的设计与应用 问题需求分析 用哈夫曼编码(Huffman Coding),又称霍夫曼编码,是一种编码方式,哈夫曼编码是可变字长编码(VLC)的一种.Huffman于1952年提出一种编码方法 ...

  9. 哈夫曼树编码和译码c语言,C++哈夫曼树编码和译码的实现

    78 /*-----------创建工作---------------------------*/ 79     int s1,s2; 80     for (int i = n + 1; i < ...

  10. 利用哈夫曼树编码与译码

    #include<iostream> #include<string.h> #include<stdlib.h> using namespace std;typed ...

最新文章

  1. juery mobile select下来菜单选项提交form问题
  2. grails springboot_groovy 使用spring boot
  3. PLSQL DEVELOPER 使用的一些技巧【转】
  4. 微服务秒杀项目整合网关+feign+redis分离热点商品分别下单示例
  5. DIV中文字不换行解决办法
  6. Web笔记-session盗用安全问题(Spring Boot获取所有session及提高安全性)
  7. (转)Cesium教程系列汇总
  8. 课程《设计模式之美》笔记之关于java四大特性
  9. OpenCV-Python教程(7、Laplacian算子)
  10. Python Des加密与解密实现软件注册码、机器码
  11. 电脑怎么分区硬盘分区方法
  12. 在埋头写程序学技术的同时,有没有想到你们的老板和上司在搞什么?
  13. Android自定义SwitchButton左右滑动开关按钮控件
  14. 腾讯程序员与医生相恋,却被女方父母拆散,你们不能在一起
  15. linux下exec用法,linux下exec系列(一)
  16. 远程ubuntu桌面_如何在Ubuntu上设置远程桌面
  17. 爬虫爬取二次元网站美女图片
  18. 【深度学习】一个用于styleGAN图像处理的编码器
  19. suspend(挂起)和resume(继续执行)线程
  20. 50个经典的增长黑客策略高效实现增长

热门文章

  1. 电机与拖动matlab仿真,Matlab仿真软件在电机与拖动中的应用
  2. Python分析与处理---利用Python进行学生成绩分析
  3. 苹果MAC系统读写NTFS格式u盘硬盘方法
  4. Redis源码分析01——基本数据结构
  5. Qt QLabel文本框的使用
  6. vue + pdf.js实现浏览器查看pdf文件
  7. 19.丑数(UVa136)
  8. ios睡眠分析 卧床 睡眠_苹果ios14睡眠记录功能 让用户清楚的了解自己的睡眠
  9. 小程序tabBar设置
  10. 当BIM遇上GIS-无人机倾斜摄影三维建模(ContextCapture) 建设智慧城市方法详解