Huffman树的编码和解码

思想:1.统计字符串每个字母出现的个数2.依次取出两个最小的字母进行合并(分别作为左右子节点,另左子节点<右子节点的值),使用他们值之和作为根节点的值,并将根节点加入到未合并的节点序列中。重复1,2操作,直到没有两个节点可以合并为止。

#include<iostream>
#include<iostream>
#include<map>
#include<vector>
using namespace std;
map<int,string> pp;//将int类型转化为对应Huffman树中的string,但是只能用于单一元的才行
map<char,int> p;//将字符转化为int类型
int len;//所得字符的个数.
struct huffmannode{float data;string ss;huffmannode*leftchild,*rightchild,*parent;huffmannode(float a=0,huffmannode* b=NULL,huffmannode* c=NULL,huffmannode* d=NULL,string s=""){ss=s;data=a;leftchild=b,rightchild=c,parent=d;}
};bool operator>= (huffmannode& io,huffmannode& p){return io.data>p.data?true:false;
}
bool operator<=(huffmannode& io,huffmannode& op){return io.data<op.data?true:false;
}template<class T>
class minheap{public:minheap(int sz=20){//建立空堆。只是给了内存空间没有数据值。maxheapsize=sz>20?sz:20;heap=new T[maxheapsize];if(heap==NULL){cout<<"内存分配错误."<<endl;exit(1);}currentsize=0;}minheap(T arr[],int n){maxheapsize=n>20?n:20;heap=new T[maxheapsize];if(heap==NULL){cerr<<"堆存储空间分配失败!"<<endl;exit(1);}for(int i=0;i<n;i++){heap[i]=arr[i];}currentsize=n;int currentpos=(currentsize-2)/2;//第一个节点位置while(currentpos>=0){siftdown(currentpos,currentsize-1);currentpos--;}};~minheap(){delete [] heap;}bool removemin(T& x);//删除堆顶元素.bool isempty(){//当当前指针指向堆首时就为真,即没有元素.if(currentsize==0){return true;}else{return false;}}bool isfull(){if(currentsize>=maxheapsize){return true;}else{return false;}}void makeempty(){currentsize=0;}bool insert(const T& io);void output(){int i=0;while(i<currentsize){cout<<heap[i++]<<" ";}}
private:T *heap;int currentsize;int maxheapsize;void siftdown(int start,int m);void siftup(int start);
};
template<class T>
void minheap<T>::siftdown(int start,int m){int i=start;T io=heap[i];T change;int j=2*i+1;//当前节点的左孩子节点while(j<=m){if(j+1<=m&&heap[j+1]<=heap[j]){change=heap[j+1];heap[j+1]=heap[j];heap[j]=change;}if(heap[j]>=io){break;}else{heap[i]=heap[j];i=j;j=j*2+1;}}heap[i]=io;
}
template<class T>
void minheap<T>::siftup(int start){int j=start,i=(j-1)/2;T temp=heap[j];while(j>0){if(heap[i]>=heap[j]){heap[j]=heap[i];j=i;i=(i-1)/2;}else{break;}}heap[j]=temp;
}
template<class T>
bool minheap<T>::insert(const T& io){if(currentsize==maxheapsize){return false;}else{heap[currentsize]=io;siftup(currentsize);currentsize++;return true;}
}
template<class T>
bool minheap<T>::removemin(T&x){if(currentsize==0){return false;}else{x=heap[0];heap[0]=heap[currentsize-1];currentsize--;siftdown(0,currentsize-1);return true;}//
}
class huffmantree{private:huffmannode *root;void deletetree(huffmannode* t);
public:void mergetree(huffmannode*& parent1,huffmannode* first,huffmannode* second){parent1=new huffmannode(first->data+second->data);parent1->leftchild=first,parent1->rightchild=second;first->parent=parent1;second->parent=parent1;}huffmantree(float *w=NULL,int n=0){minheap<huffmannode> hp;huffmannode *first,*second,work;huffmannode *parent1;for(int i=0;i<n;i++){work.data=w[i];work.leftchild=NULL,work.rightchild=NULL,work.parent=NULL;hp.insert(work);}for(int i=0;i<n-1;i++){//通过个数限定解决可能first和second无值的情况.注意removemin返回的是bool类型,first=new huffmannode;second= new huffmannode;hp.removemin(*first);hp.removemin(*second);mergetree(parent1,first,second);hp.insert(*parent1);//insert是插入到最小堆中所以他的第一和第二小元素是有先后顺序的}root=parent1;//将最终的父节点赋值给root节点.}huffmannode* getroot(){return root;}void bianma(huffmannode*&op){//根节点初始化为空字符串if(op==NULL){return;}if(op->rightchild==NULL&&op->leftchild==NULL){//尾节点就是我们要的解,即编码后的字符串.pp[op->data]=op->ss;return;//记得返回,因为之后为NULL了但是又没有判断条件}if(op->leftchild!=NULL){op->leftchild->ss=op->ss+"0";}if(op->rightchild!=NULL){op->rightchild->ss=op->ss+"1";}bianma(op->leftchild);bianma(op->rightchild);}void  jiema(string  oo,vector<char> &io,string op,int left){//不能直接使用io的长度因为可能长度过长,不是他的实际长度if(left==op.length()){//这种条件下,如果满足了会回到原来的位置,cout<<oo<<endl;//可能存在多种解return;}for(int i=0;i<len;i++){if(op.substr(left,(pp[p[io[i]]]).size())==pp[p[io[i]]]){oo+=io[i];int cnt=left;cnt+=pp[p[io[i]]].size();//因为从0开始jiema(oo,io,op,cnt);//使用这样的局部变量才能在这次满足之后下一个循环再使用时为原来的起始值。。}}return;//表示失败时自动返回}
};
void output(huffmannode&op) {if (op.data == 0)return;cout << op.data << endl;if (op.leftchild == NULL) {cout << "true" << endl;}cout << (*op.leftchild).data << endl;output(*op.leftchild);output(*op.rightchild);
}
int main() {string str;cin >> str;for (int i = 0; i < str.length(); i++) {if (!p.count(str[i])) {p[str[i]] = 1;} else {p[str[i]]++;}}map<char, int>::iterator io = p.begin();float *i = new float[100];vector<char> ent(str.length(), 0);for (; io != p.end(); io++) {i[len] = io->second;ent[len] = io->first;cout << i[len] << endl;len++;}huffmantree ip(i, len);huffmannode *end = ip.getroot();//Huffman编码ip.bianma(end);for (int k = 0; k < len; k++) {cout << ent[k] << "的编码为" << pp[p[ent[k]]] << endl;}string iop;cin >> iop;string re = "";//Huffman解码ip.jiema(re, ent, iop, 0);return 0;
}

求解字符串队列哈夫曼序列的长度

#include <bits/stdc++.h>  //万能头文件,vs2019中需自己设置
using namespace std;
string s;
map<char, int> mp;
priority_queue<int, vector<int>, greater<int>> q; //升序排列int main()
{getline(cin, s);int len = s.length();for (int i = 0; i < len; i++) {   //记录字符与其对应的出现的次数if (mp.find(s[i]) == mp.end()) {mp[s[i]] = 1;} else {mp[s[i]]++;}}for (map<char, int>::iterator it = mp.begin(); it != mp.end(); it++) {q.push(it->second); //字符出现的次数入队}int ans = 0;//记录结果while (q.size() != 1) {int a, b, temp;//a,b记录最小的两个次数a = q.top();q.pop();b = q.top();q.pop();temp = a + b; //队列中最小的两个次数相加ans += temp;q.push(temp);//最小的两个次数相加再次入队,优先队列自行排序}cout << ans << endl;return 0;
}

数据结构-Huffman树相关推荐

  1. Java学习——数据结构——Huffman树

    学习尚硅谷韩顺平老师的Java数据结构笔记,详情请移步网站 1.介绍 (1) 给定 n 个权值作为 n 个叶子结点,构造一棵二叉树,若该树的带权路径长度(wpl)达到最小,称这样的二叉树为最优二叉树, ...

  2. 数据结构 Huffman树(霍夫曼树、哈夫曼树)

    Huffman树 给定N个权值作为N个叶子结点,构造一棵二叉树,若该树的带权路径长度达到最小,称这样的二叉树为最优二叉树,也称为哈夫曼树(Huffman Tree).哈夫曼树是带权路径长度最短的树,权 ...

  3. 数据结构源码笔记(C语言):Huffman树字符编码

    #include <stdio.h> #include<string.h> #define N 10 /*待编码字符的个数,即树中叶结点的最大个数*/ #define M 2* ...

  4. 二叉树应用-Huffman树类模板的实现(数据结构基础 第6周)

    简单实现来了Huffman树,在找最小堆的过程中使用到了自己做的最小堆MinHeap. 之前写的关于树的类模板中一直存在一个问题:结点的内存管理太混乱,有些甚至存在临时变量里.这里直接在类内直接定义了 ...

  5. 数据结构实验三:Huffman树及Huffman编码的算法实现

    Exp03 Huffman树及Huffman编码的算法实现 Author: Maskros 实验目的 了解该树的应用实例,熟悉掌握Huffman树的构造方法及Huffman编码的应用, 了解Huffm ...

  6. 数据结构入门----赫夫曼Huffman树及其应用

    最优二叉树(霍.赫.哈夫曼树) 路    径: 由一结点到另一结点间的分支所构成. 路径长度: 路径上的分支数目.a→e的路径长度=2 树的路径长度: 从树根到每一结点的路径长度之和.树长度=10 带 ...

  7. [数据结构复习]树_二叉树

    1.二叉树的一些性质: 对于一棵非空二叉树,如果其叶节点数为n0,度为2的非叶节点数为n2,则n0=n2+1. 证明可以从边数的不同表示方法着手. 具有N个结点的完全二叉树的深度为log2(n+1)取 ...

  8. 数据结构-王道-树和二叉树

    [top] 树和二叉树 树:是\(N(N\geq0)\)个结点的有限集合,\(N=0\)时,称为空树,这是一种特殊情况.在任意一棵非空树中应满足: 有且仅有一个特定的称为根的结点. 当\(N>1 ...

  9. 心中有“树”:数据结构之树详解

    文章目录 前言 (一)树的基础定义与表示 1 树的定义 2 树的图示 3 树的逻辑结构表示法 (二)二叉树 1 二叉树定义 2 二叉树示意图 3 程序实现 (1)节点定义 (2)二叉树的先序遍历 (3 ...

最新文章

  1. 诚意租房网blog2
  2. 京沪深月薪均超2万元,清华近三成毕业生年入50万+ | 2019上半年中高端人才就业现状报告...
  3. ??ArcGIS server公交线路动态分段问题
  4. 一分钟了解 Matlab求两个矩阵的相关程度corr2
  5. 2020年电大c语言程序设计作业1答案,2019年最新电大C语言程序设计作业答案.doc
  6. NYOJ 108 士兵杀敌(一)
  7. EF中使用数据库的标量值函数
  8. windows mac linux 木马,针对Linux Windows macOS系统Adwind木马广告攻击
  9. 养老院管理系统如何开发详解
  10. 天刀帐号角色服务器查询系统,天涯明月刀手游角色交易介绍-角色转移系统
  11. 全国路网数据SHP、全国矢量数据 行政区划边界(省市区县乡镇)、行政地名
  12. 广告法违禁词替换工具_广告法禁用词替代大全之第一弹
  13. 使用List和Map遇到得空指针异常
  14. 2020湖南省技能竞赛获奖名单_2020年全国职业院校技能大赛教学能力比赛落幕 湖南获一等奖数量排全国第一...
  15. 手气不错 跳过搜索 谷歌 Google
  16. android微信post提交表单,微信自带浏览器不支持form表单post提交方案解决
  17. 微信支付商户号的调研
  18. js计算两个日期时间的差值
  19. python脚本文件的扩展命是什么_一些文件的扩展名
  20. vite2 antD 动态切换主题

热门文章

  1. 大量的QT控件及示例发放
  2. 逆向工程核心原理读书笔记-API钩取之隐藏进程(一)
  3. 关于 ADB 实现的说明
  4. C++ 面向对象(一)继承:继承、对象切割、菱形继承、虚继承、继承与组合
  5. 线程、进程、多线程、多进程和多任务有啥关系?
  6. 几种常见的Web攻击
  7. LeetCode 打家劫舍问题
  8. 技术实战 —— 快速实现语聊房搭建
  9. TikTok 英国业务亏损、苹果从中国应用商店下架近4万款游戏、Zoom 接受调查等|Decode the Week...
  10. 腾讯云张贤国:北大将我从少年变成了技术研究者