该哈夫曼树可以实现的功能:
(1)能够通过键盘或者纯文本文件读入字符集的大小n,以及n个字符和权值来建立哈夫曼树,并且把建立好的哈夫曼树存入到HuffmanTree.txt中去。
(2)利用已经建立好的哈夫曼树,对文件中的正文进行编码,将结果存入到文件HuffmanCode.txt中。
(3)利用已经建立好的哈夫曼树将HuffmanCode.txt中的哈夫曼编码进行译码,结果存入到HuffmanText.txt中。
(4)能够按照垂直输出二叉树的方式,将存储在HuffmanTree.txt纯文本文件中的哈夫曼树垂直输出。并且在打印哈夫曼编码是,要求字符与编码之间是一一对应的。


实现提示:
(1)在程序运行时,能够出现一个主选择菜单,用户能够自主选择功能:①建立哈夫曼树;②对哈夫曼树进行编码、译码等功能。
(2)在建立哈夫曼树时,用到文本文件的读取时,需要用到头文件“fstream”来对文本文件进行处理。

#include<iostream>
#include<algorithm>
#include<cstring>
#include<vector>
#include<list>
#include<iomanip>
#include<fstream>
using namespace std;
template<class T>
class Queue {//重新构建优先队列
private:list<T>queue;
public:Queue() {}~Queue() {}int Empty() { return queue.empty(); }int Size() { return queue.size(); }void Push(const T& item) { queue.push_back(item); }T Pop() { T item = queue.front(); queue.pop_front(); return item; }void Clear() { queue.clear(); }
};
template<class T>
struct BTNode {//定义二叉树结构体 T data;BTNode* left, * right;//left-代表左节点  right-代表右节点 BTNode(const T& item = T(), BTNode* lp = NULL, BTNode* rp = NULL) :data(item), left(lp), right(rp) {}//初始化
};
template<class T>
BTNode<T>* GetNode(const T& item, BTNode<T>* lp = NULL, BTNode<T>* rp = NULL){//创建节点 BTNode<T>* p;p = new BTNode<T>(item, lp, rp);if (p == NULL){cout << "the new is faliure" << endl;exit(1);}return p;
}template<class T>
BTNode<T>* MAkeLinkd(const vector<T>& l)//将存储在vector向量类模版中的元素(也就是顺序存储)转换为链式存储
{if (l.size() == 0)return 0;Queue<BTNode<T>*>Q;BTNode<T>* parent, * child;BTNode<T>* t = GetNode(l[0]);Q.Push(t);int i = 0, n = l.size();while (!Q.Empty()){parent = Q.Pop();if (2 * i + 1 < n && l[2 * i + 1] != T())//构建左节点 {child = GetNode(l[2 * i + 1]);parent->left = child;Q.Push(child);}if (2 * i + 2 < n && l[2 * i + 2] != T())//构建右节点 {child = GetNode(l[2 * i + 2]);parent->right = child;Q.Push(child);}i++;while (i < n && l[i] == T())i++;}return t;
}
struct Location {//定义垂直输出二叉树的高度和宽度 int xindent, ylevel;
};
void GOtoxy(int x, int y){static int levelt = 0, indent = 0;if (y == 0){y = 0; levelt = 0;}if (y != levelt) {cout<<endl;levelt++;indent = 0;}cout.width(x - indent);indent = x;
}
template<class T>
void PrintBTNode(const BTNode<T>* t, int sreenwidth){//垂直输出二叉树 if (!t)return;int offest = sreenwidth / 2, levels = 0;Location flex, loc;Queue<const BTNode<T>*>Q;Queue<Location>lQ;flex.xindent = offest;flex.ylevel = levels;Q.Push(t);lQ.Push(flex);while (!Q.Empty()){t = Q.Pop();flex = lQ.Pop();GOtoxy(flex.xindent, flex.ylevel);cout << t->data;if (flex.ylevel != levels){levels++;offest = offest / 2;}if (t->left){Q.Push(t->left);loc.ylevel = flex.ylevel + 1;loc.xindent = flex.xindent - offest / 2;lQ.Push(loc);}if (t->right){Q.Push(t->right);loc.ylevel = flex.ylevel + 1;loc.xindent = flex.xindent + offest / 2;lQ.Push(loc);}}cout << endl;
}template<class T>
class Heap {//定义堆类
private:vector<T>vec;int size;void BuildHeap();void PercolateDown(int h);//向下调整为堆 void PercolateUp();//向上调整为堆
public:explicit Heap(int max = 100) :vec(max), size(0) {} explicit Heap(const vector<T>& vt);bool Empty()const{return size == 0;}// 判断堆是否为空 int Size() {return size;}//返回元素数量 void Insert(const T& item);//向堆中插入元素 const T& Top()const {return vec[0];}//返回第一个元素 void Deletemin();//删除最小的元素 void Deletemin(T& item);//删除最小的元素并保存 void Clear() {size = 0;}//清空堆
};
template<class T>
Heap<T>::Heap(const vector<T>& vt) :vec(vt.size() + 10), size(vt.size()){for (int i = 0; i < size; i++){vec[i] = vt[i];}BuildHeap();
}
template<class T>
void Heap<T>::BuildHeap(){for (int i = size / 2 - 1; i >= 0; i--){PercolateDown(i);}
}
template<class T>
void Heap<T>::PercolateDown(int h){int p = h, c = 2 * p + 1;T temp = vec[p];while (c < size){if (c + 1 < size && vec[c + 1] < vec[c]){c++;}if (temp <= vec[c]){break;}else{vec[p] = vec[c];p = c;c = 2 * p + 1;}}vec[p] = temp;
}
template<class T>
void Heap<T>::PercolateUp(){int c = size - 1, p = (c - 1) / 2;T temp = vec[c];while (c > 0){if (temp >= vec[p]) {break;}else{vec[c] = vec[p];c = p;p = (c - 1) / 2;}}vec[c] = temp;
}
template<class T>
void Heap<T>::Insert(const T& item){if (size == vec.size()){vec.resize(vec.size() * 2);}vec[size++] = item;PercolateUp();
}template<class T>
void Heap<T>::Deletemin(){if (size <= 0)return;vec[0] = vec[size - 1];size--;PercolateDown(0);
}
template<class T>
void Heap<T>::Deletemin(T& item){if (size <= 0)return;item = vec[0];vec[0] = vec[size - 1];size--;PercolateDown(0);
}
template<class T>
void BuildHeapMax(T* pa, int size){for (int i = size / 2 - 1; i >= 0; i--){PercolateDown(pa, size);}
}
template<class T>
struct HufmNode {//构建哈夫曼结构体 BTNode<T>* t;//类型为二叉树类型 int operator<(const HufmNode& h) {return (t->data < h.t->data);}//重载< int operator<=(const HufmNode& h) {return (t->data <= h.t->data);}// 重载<= int operator>=(const HufmNode& h) {return (t->data >= h.t->data);}//重载>=
};template<class T>
BTNode<T>* MakeHufm(const T*pa, int n)//构建哈夫曼树
{HufmNode<T>hf;BTNode<T>* t, * left, * right;Heap<HufmNode<T> >H(n);for (int i = 0; i < n; i++){//构建堆 t = GetNode(pa[i]);hf.t = t;H.Insert(hf);}for (int i = 1; i < n; i++){//每一次从堆中获取最小的两个元素,作为左节点和右节点(注意右节点元素大于左节点元素) H.Deletemin(hf);left = hf.t;H.Deletemin(hf);right = hf.t;t = GetNode(left->data + right->data, left, right);hf.t = t;H.Insert(hf);}H.Deletemin(hf);t = hf.t;return t;
}ofstream fout1("D:\\HuffmanTree.txt",ios_base::out|ios_base::binary);//将构建的哈夫曼树存储在D:\\HuffmanTree.txt
struct Locations {int xindent, ylevel;
};
void GOtoxys(int x, int y){static int levelt = 0, indent = 0;if (y == 0){y = 0; levelt = 0;}if (y != levelt) {fout1<<endl;levelt++;indent = 0;}fout1.width(x - indent);indent = x;
}
template<class T>
void WriteHuffnode(const BTNode<T>*t,int w){//在D:\\HuffmanTree.txt垂直输出哈夫曼树 if(!fout1){cout<<"the HuffmanTree.txt is not open\n";exit(1);}if (!t)return;int offest = w / 2, levels = 0;Locations flex, loc;Queue<const BTNode<T>*>Q;Queue<Locations>lQ;flex.xindent = offest;flex.ylevel = levels;Q.Push(t);lQ.Push(flex);while (!Q.Empty()){t = Q.Pop();flex = lQ.Pop();GOtoxys(flex.xindent, flex.ylevel);fout1 << t->data<<" ";if (flex.ylevel != levels){levels++;offest = offest / 2;}if (t->left){Q.Push(t->left);loc.ylevel = flex.ylevel + 1;loc.xindent = flex.xindent - offest / 2;lQ.Push(loc);}if (t->right){Q.Push(t->right);loc.ylevel = flex.ylevel + 1;loc.xindent = flex.xindent + offest / 2;lQ.Push(loc);}}
}
template<class T>
void Huffmcode(const BTNode<T>*t,int codes[],int parenth){//输出对应字符的哈夫曼编码,从根节点开始向下遍历,在终端窗口输出 if(t!=NULL){if(t->left==NULL&&t->right==NULL){cout<<"字符:"<<"<"<<t->data<<">"<<" the code"<<'\t'; for(int j=0;j<parenth;j++){cout<<codes[j];}cout<<endl;return ;}else{if(t->left!=NULL){//遇到左节点时标记为0,codes[parenth]=0;Huffmcode(t->left,codes,parenth+1);}if(t->right!=NULL){//遇到右节点时标记为1codes[parenth]=1;Huffmcode(t->right,codes,parenth+1);}}}
}
ofstream fouts("D:\\HuffmanCode.txt",ios_base::out|ios_base::binary);//将哈夫曼编码存储在 D:\\HuffmanCode.txt
template<class T>
void WriteHuffmcode(const BTNode<T>*t,int codes[],int parenth){//输出对应字符的哈夫曼编码,从根节点开始向下遍历,在记事本中输出 if(!fouts){cout<<"the HuffmanCode.txt is not open\n";exit(1);}if(t!=NULL){if(t->left==NULL&&t->right==NULL){fouts<<"字符:"<<"<"<<t->data<<">"<<" is the code"<<'\t'; for(int j=0;j<parenth;j++){fouts<<codes[j];}fouts<<endl;return ;}else{if(t->left!=NULL){//遇到左节点时标记为0,codes[parenth]=0;WriteHuffmcode(t->left,codes,parenth+1);}if(t->right!=NULL){//遇到右节点时标记为1codes[parenth]=1;WriteHuffmcode(t->right,codes,parenth+1);}}}
}
int  code[50];
int parenth;
template<class T>
void HuffmancodeBTN(const BTNode<T>*t){if(t==NULL)return ;if(t!=NULL){if(t->left!=NULL){code[parenth++]=0;HuffmancodeBTN(t->left); }if(t->right!=NULL){code[parenth++]=1;HuffmancodeBTN(t->right); }}
}
template<class T>
void HuffmanText(const BTNode<T>*t) {//根据哈夫曼编码输出对应的字符(译码) if(t!=NULL){if(t->left==NULL&&t->right==NULL){cout<<"The code is:"<<"<<"<<t->data<<">>";}cout<<endl;if(code[parenth++]==0&&t->left!=NULL){HuffmancodeBTN(t->left);}if(t->right!=NULL&&code[parenth++]==1){HuffmancodeBTN(t->right);}}
}
int k;
ofstream fout("D:\\HuffmanText.txt",ios_base::out|ios_base::binary);//将译码存储在 D:\\HuffmanText.txt
template<class T>
void PreHuffmannode_1(const BTNode<T>*t){//根据哈夫曼编码输出对应的字符 ,存储在记事本中 if(!fout){cout<<"the HuffmanText.txt is not open\n";exit(1);}if(t==NULL)return ;if(t->left==NULL&&t->right==NULL){//printf("The %d code is %d\n",k++,t->data);fout<<"The "<<k++<<" code is:"<<t->data<<endl;}if(t->left!=NULL){PreHuffmannode_1(t->left);}if(t->right!=NULL){PreHuffmannode_1(t->right);}
}
int j;
template<class T>
void PreHuffmannode_2(const BTNode<T>*t){// 根据哈夫曼编码输出对应的字符 ,显示在终端窗口上 if(t==NULL)return ;if(t->left==NULL&&t->right==NULL){printf("The %d code is %d\n",j++,t->data);}if(t->left!=NULL){PreHuffmannode_2(t->left);}if(t->right!=NULL){PreHuffmannode_2(t->right);}
}
int main()
{int a[50];int item,count=0,i=0;char s;cout<<"Please enter the operator:\n"<<endl;//清单列表,根据对应的功能输入对应的大写字母,即可实现,可以在终端窗口看到输出结果,也可以在记事本中看到保存的结果 cout<<"The A--------------建立垂直哈夫曼树------------------------------------"<<endl;cout<<"The B--------------输出哈夫曼编码--------------------------------------"<<endl;cout<<"The C--------------对应的编码译码并保存文件(HuffmanText.txt)---------"<<endl;cout<<"The D--------------将输出对应输出的编码译码-----------------------------"<<endl;cout<<"The E--------------哈夫曼编码保存文件中(HuffmanCode.txt)--------------"<<endl;cout<<"The F--------------哈夫曼树并保存文件(HuffmanTree.txt)------------------"<<endl;cout<<"The Q-------------START Please entor the number and the item is zero end"<<endl;BTNode<int>* root;root=NULL;int codes[50];while(cin>>s){//可以一直构建哈夫曼树,但是要清空之前的哈夫曼树 if(s=='#')break;if(s=='Q'){memset(a,0,sizeof(a));memset(codes,0,sizeof(codes));cin>>item;i=0;root=NULL;//root指向空 while(item!=0){//当输入为零,代表输入结束 a[i]=item;i++;cin>>item;}}root = MakeHufm(a, i);switch(s){case 'A':PrintBTNode(root, 40);break;case 'B':Huffmcode(root,codes,0);cout<<endl;break;case 'C':k=1;PreHuffmannode_1(root);cout<<"D:\\HuffmanText.txt!保存成功!"<<endl;break;case 'D':j=1;PreHuffmannode_2(root);cout<<endl; break; case 'E': WriteHuffmcode(root,codes,0);cout<<"D:\\HuffmanCode.txt!保存成功!"<<endl;break;case 'F':WriteHuffnode(root,40);cout<<"D:\\HuffmanTree.txt保存成功!"<<endl;break;}}
//  parenth=0;
//  HuffmancodeBTN(root);
//  parenth=0;
//  HuffmanText(root);return 0;
}








关于C++类实现哈夫曼树相关推荐

  1. Python---哈夫曼树---Huffman Tree

    今天要讲的是天才哈夫曼的哈夫曼编码,这是树形数据结构的一个典型应用. !!!敲黑板!!!哈夫曼树的构建以及编码方式将是我们的学习重点. 老方式,代码+解释,手把手教你Python完成哈夫曼编码的全过程 ...

  2. 三十、赫夫曼树的设计与代码实现

    一.基本介绍 给定 n 个权值作为 n 个叶子结点,构造一棵二叉树,若该树的带权路径长度(wpl)达到最小,称这样的二叉树为 最优二叉树,也称为哈夫曼树(Huffman Tree), 还有的书翻译为霍 ...

  3. 学习日志---哈夫曼树相关算法

    哈夫曼树概念: 如果二叉树中的叶结点都带有权值,我们可以把这个定义加以推广.设二叉树有n个带权值的叶结点,定义从二叉树的根结点到二叉树中所有叶结点的路径长度与相应叶结点权值的乘积之和为该二叉树的带权路 ...

  4. Java数据结构和算法:哈夫曼树

    本章介绍哈夫曼树.和以往一样,本文会先对哈夫曼树的理论知识进行简单介绍,然后给出C语言的实现.后续再分别给出C++和Java版本的实现:实现的语言虽不同,但是原理如出一辙,选择其中之一进行了解即可.若 ...

  5. 深度解析(十五)哈夫曼树

    哈夫曼树(一)之 C语言详解 本章介绍哈夫曼树.和以往一样,本文会先对哈夫曼树的理论知识进行简单介绍,然后给出C语言的实现.后续再分别给出C++和Java版本的实现:实现的语言虽不同,但是原理如出一辙 ...

  6. 【赫夫曼树详解】赫夫曼树简介及java代码实现-数据结构07

    赫夫曼树(最优二叉树) 1. 简介 定义: 赫夫曼树是n个带权叶子结点构成的所有二叉树中,带权路径长度(WPL)最小的二叉树. 叶子结点的带权路径: 叶子结点权值*到根节点的路径长度(叶结点的层数) ...

  7. 霍夫曼树(最优二叉树)的实现

    文章目录 一.相关概念 1.节点的路径及路径长度 2.节点的带权路径长度 3.树的带权路径长度 4.霍夫曼树 二.构建步骤与图解 1.构建步骤 2.图解 三.代码实现 1.创建节点类: 2.创建霍夫曼 ...

  8. 【大话数据结构算法】哈夫曼树

    哈夫曼树又称为最优二叉树. 1.路径和路径长度 在一棵树中,从一个节点往下可以达到的孩子或者子孙节点之间的通路称为路径.通路中分支的数目称为路径长度.若规定根节点的层数为1,则从根节点 到第L层节点的 ...

  9. python哈夫曼树_python霍夫曼树

    class Node(): data=0 left=None right=None father=None def __init__(self,data,left,right): self.data= ...

最新文章

  1. Yii2 定时任务创建(Console 任务)
  2. SQL Where in list 问题
  3. 数学猜想验证步骤_高中数学解题思路与技巧汇总,19种解题方法,实用!
  4. 软件测试之-测试用例写作规范
  5. 企业域名更换操作系列4:下载旧域域信息配置
  6. linux c libcurl的简单使用
  7. 延边大学计算机考研经验分享
  8. 复合型网络拓扑结构图_计算机网络拓扑结构图的种类及图示
  9. G33/G31芯片最佳分辨率1440×900
  10. qpython3 l_QPython 3(com.hipipal.qpy3) - 3.0.0 - 应用 - 酷安网
  11. 增加收入的销售 OKR 案例 – 用这些 OKR 范例来设定你的销售团队目标
  12. 日常工作记录:AlertDialog中的取消、确定按钮显示不到问题
  13. light动名词_动名词与高考考点解析
  14. SQL Sever创库
  15. 中国中老年服装市场投资前景分析及供需格局研究预测报告
  16. Arduino开发板DIY简易机械臂
  17. 买卖股票的最优时机含手续费(LeetCode-714)
  18. 【GANs】C-RNN-GAN
  19. C语言斗地主课程设计,智能斗地主课程设计论文.doc
  20. 八、HTML常用标签

热门文章

  1. 美多商城之商品(商品搜索)
  2. 神经网络基础知识总结
  3. 目标检测中的Tricks
  4. 熬了几个大夜,学完一套985博士总结的「卷积神经网络、目标检测、OpenCV」学习笔记(20G高清/PPT/代码)...
  5. 收藏 | 各种 Optimizer 梯度下降优化算法回顾和总结
  6. 每日一题(进制转换)
  7. HI3519安装SDK错误
  8. linux系统资源监控
  9. Python3经典100例(③)
  10. 详解JVM内存管理与垃圾回收机制3 - JVM中对象的内存布局