精华内容
下载资源
问答
  • 每组数据个数为 1920×1080,并对这三组数据分别进行哈夫曼编码解码。计算熵和码字的平均码长。 (2)将彩色图像的像素 R、G、B 值作为独立符号,进行哈夫曼编码解码,计算熵和码字平均码长。 (3)将彩色图像的...
  • NULL 博文链接:https://touch-2011.iteye.com/blog/1058800
  • 哈夫曼编码与解码

    2015-05-29 20:50:23
    文档提供构造哈夫曼编码与解码,构造哈夫曼树。
  • 基于STM32F103实现的美的空调的遥控功能,通过分析美的空调的外红时序图来进行编码与解码
  • 绝对原创的哈夫曼编码与解码。自己输入文件名称,然后统计文件中各个字符出现的次数,计算出每个字符的哈夫曼编码和整篇文章的哈夫曼编码,然后打印出哈夫曼树。最后对整篇文章的哈夫曼编码进行解码
  • 哈夫曼树的编码与解码

    千次阅读 2019-12-21 22:30:04
    DS二叉树——Huffman编码与解码 哈夫曼树简介 给定N个权值作为N个叶子结点,构造一棵二叉树,若该树的带权路径长度达到最小,称这样的二叉树为最优二叉树,也称为哈夫曼树。哈夫曼树是带权路径长度最短的树,权值较...

    DS二叉树——Huffman编码与解码

    哈夫曼树简介

    给定N个权值作为N个叶子结点,构造一棵二叉树,若该树的带权路径长度达到最小,称这样的二叉树为最优二叉树,也称为哈夫曼树。哈夫曼树是带权路径长度最短的树,权值较大的结点离根较近。
    在这里插入图片描述
    在这里插入图片描述

    • 根据数据出现的频率,使用不同长度的编码

    一段文字由x个字符组成,每个字符的出现频率不同,比如a出现114514次,而c只出现了810次,如果对a使用短长度的编码(比如01),对b使用较长的编码(比如01011),相比于使用同样长度的编码(00001 与 01011),可使编码效率变高

    题目

    • 给定n个字符及其对应的权值,构造Huffman树,并进行huffman编码和译(解)码。
    • 构造Huffman树时,要求左子树根的权值小于、等于右子树根的权值。
    • 进行Huffman编码时,假定Huffman树的左分支上编码为‘0’,右分支上编码为‘1’。

    输入
    第一行测试次数
    第2行:第一组测试数据的字符个数n,后跟n个字符
    第3行:第一组测试数据的字符权重 待编码的字符串s1 编码串s2

    输出
    第一行~第n行,第一组测试数据各字符编码值
    第n+1行,串s1的编码值
    第n+2行,串s2的解码值,若解码不成功,输出error!

    样例输入
    2 5 A B C D E
    15 4 4 3 2
    ABDEC
    00000101100
    4 A B C D
    7 5 2 4
    ABAD
    1110110

    样例输出
    A :1
    B :010
    C :011
    D :001
    E :000
    1010001000011
    error!
    A :0
    B :10
    C :110
    D :111
    0100111
    DAC

    哈夫曼树的构造规则

    共有 n 个不同的字符需要编码,编码规则如下:

    • 每次合并,选择没有被选择的,两个权值最小的根节点:x1, x2,将他们的合并
    • 合并之后的根节点的权值是 x1的权值 + x2的权值
    • 合并之后的根节点仍然可以作为新的根节点被选择
    • 需要合并 n-1 次,最后剩下一个根,就是哈夫曼树的根

    使用顺序结构(数组)构造哈夫曼树

    初始状态:
    在这里插入图片描述

    第一次合并,选择 2,3 合并 在这里插入图片描述 在这里插入图片描述

    第二次合并,选择 4, 4 在这里插入图片描述 在这里插入图片描述

    第三次合并,选择 5, 8
    在这里插入图片描述
    在这里插入图片描述

    第四次合并,选择 15, 13
    在这里插入图片描述
    在这里插入图片描述

    哈夫曼树结构实现与创建:

    #define maxlen 100
    
    // 哈夫曼树节点类
    class hft_node
    {
    public:
    	hft_node();
    	int weight;
    	int parent;
    	int lchild;
    	int rchild;
    	char ch;		// 该节点代表的字符
    	string code;	// 该节点字符对应的编码
    };
    
    hft_node::hft_node()
    {
    	this->lchild = -1;
    	this->rchild = -1;
    	this->parent = -1;
    }
    
    // 哈夫曼树类
    class hft
    {
    public:
    	hft();
    	int n;					// 需要编码的字符个数
    	hft_node nodes[maxlen];	// 节点
    	int visited[maxlen];	// 选择标识数组
    	
    	// 找两个未被选择的最小权值节点
    	void min2(int &index1, int &m1, int &index2, int &m2, int range);
    	void encode(string s);	// 获得字符的01编码
    	void decode(string s);	// 对01编码解码获得字符串
    };
    

    创建哈夫曼树

    • 找两个最小权值且未被选择的节点:函数实现
    void hft::min2(int &index1, int &m1, int &index2, int &m2, int range)
    {
    	int i;
    	int min = 114514;
    	int min_index = 0;
    	
    	// min
    	for(i=0; i<range; i++)
    	{
    		if(visited[i]==0 && min>nodes[i].weight)
    		{
    			min = nodes[i].weight;
    			min_index = i;
    		}
    	}
    	visited[min_index] = 1;
    	m1 = min;
    	index1 = min_index;
    	
    	// sub min
    	min = 114514;
    	min_index = 0;
    	for(i=0; i<range; i++)
    	{
    		if(visited[i]==0 && min>nodes[i].weight)
    		{
    			min = nodes[i].weight;
    			min_index = i;
    		}
    	}
    	visited[min_index] = 1;
    	m2 = min;
    	index2 = min_index;
    }
    
    • 两两合并节点
    // build hfm tree
    	for(i=n; i<2*n-1; i++)
    	{
    		int idx1, m1, idx2, m2;
    		min2(idx1, m1, idx2, m2, i);
    		
    		nodes[i].weight = m1 + m2;
    		nodes[i].lchild = idx1;
    		nodes[i].rchild = idx2;
    		nodes[idx1].parent = i;
    		nodes[idx2].parent = i;
    	}
    

    哈夫曼树编码

    在这里插入图片描述 在这里插入图片描述

    // hft coding
    #define push push_back
    #define pop pop_back
    #define top back
    for(i=0; i<n; i++)	// 对每个叶子,下标: 0~n-1 进行编码
    {
    	deque<char> s;
    	int x = i;
    	while(1)
    	{	
    		int pa = nodes[x].parent;
    		if(pa == -1)
    		{
    			break;
    		}
    		
    		if(nodes[pa].lchild == x)
    		{
    			s.push('0');
    		}
    		else
    		{
    			s.push('1');
    		}
    		x = pa;
    	}
    	
    	// 因为是由叶子向根回溯,需要逆序输出才是真正的编码结果
    	while(!s.empty())
    	{
    		nodes[i].code += s.top();
    		s.pop();
    	}
    }// end of hft coding
    

    对给定的字符串,得到它的01编码

    void hft::encode(string s)
    {
    	for(int i=0; i<s.length(); i++)
    	{
    		char c = s[i];
    		for(int j=0; j<n; j++)
    		{
    			if(c == nodes[j].ch)
    			{
    				cout<<nodes[j].code;
    				break;
    			}
    		}
    	}
    	cout<<endl;
    }
    

    给定一串01串,得到解码后的字符串

    void hft::decode(string s)
    {
    	deque<char> q;	// 队列保存解码结果
    	
    	int x = 2*n-2;	// 从根节点出发
    	for(int i=0; i<s.length(); i++)
    	{
    		if(s[i] == '0')
    		{
    			x = nodes[x].lchild;
    		}
    		else 
    		{
    			x = nodes[x].rchild;
    		}
    		
    		// 如果是叶子,解码完成
    		if(nodes[x].lchild==-1 && nodes[x].rchild==-1)
    		{
    			q.push_back(nodes[x].ch);
    			x = 2*n-2;	// 下一次循环再次从根出发
    		}
    	}
    	
    	// 如果读取01串之后,没有到达叶子节点,出错
    	if(n<=x && x<2*n-2)
    	{
    		cout<<"error!"<<endl;
    	}
    	else 
    	{
    		while(!q.empty())
    		{
    			cout<<q.front();
    			q.pop_front();
    		}
    		cout<<endl;
    	}
    }
    

    完整代码

    #include <iostream>
    #include <string>
    #include <deque>
    
    using namespace std;
    #define maxlen 100
    
    class hft_node
    {
    public:
    	hft_node();
    	int weight;
    	int parent;
    	int lchild;
    	int rchild;
    	char ch;
    	string code;
    };
    
    hft_node::hft_node()
    {
    	this->lchild = -1;
    	this->rchild = -1;
    	this->parent = -1;
    }
    
    class hft
    {
    public:
    	hft();
    	int n;
    	hft_node nodes[maxlen];	
    	int visited[maxlen];
    	
    	void min2(int &index1, int &m1, int &index2, int &m2, int range);
    	void encode(string s);
    	void decode(string s);
    };
    
    void hft::min2(int &index1, int &m1, int &index2, int &m2, int range)
    {
    	int i;
    	int min = 114514;
    	int min_index = 0;
    	
    	// min
    	for(i=0; i<range; i++)
    	{
    		if(visited[i]==0 && min>nodes[i].weight)
    		{
    			min = nodes[i].weight;
    			min_index = i;
    		}
    	}
    	visited[min_index] = 1;
    	m1 = min;
    	index1 = min_index;
    	
    	// sub min
    	min = 114514;
    	min_index = 0;
    	for(i=0; i<range; i++)
    	{
    		if(visited[i]==0 && min>nodes[i].weight)
    		{
    			min = nodes[i].weight;
    			min_index = i;
    		}
    	}
    	visited[min_index] = 1;
    	m2 = min;
    	index2 = min_index;
    }
    
    hft::hft()
    {
    	cin>>n;
    	int i;
    	for(i=0; i<n; i++)
    	{
    		cin>>nodes[i].ch;
    	}
    	
    	for(i=0; i<n; i++)
    	{
    		cin>>nodes[i].weight;
    	}
    	
    	for(i=0; i<2*n; i++)
    	{
    		visited[i] = 0;
    	}
    	
    	// build hfm tree
    	for(i=n; i<2*n-1; i++)
    	{
    		int idx1, m1, idx2, m2;
    		min2(idx1, m1, idx2, m2, i);
    		
    		nodes[i].weight = m1 + m2;
    		nodes[i].lchild = idx1;
    		nodes[i].rchild = idx2;
    		nodes[idx1].parent = i;
    		nodes[idx2].parent = i;
    	}
    	
    	// hft coding
    	#define push push_back
    	#define pop pop_back
    	#define top back
    	for(i=0; i<n; i++)
    	{
    		deque<char> s;
    		int x = i;
    		while(1)
    		{	
    			int pa = nodes[x].parent;
    			if(pa == -1)
    			{
    				break;
    			}
    			
    			if(nodes[pa].lchild == x)
    			{
    				s.push('0');
    			}
    			else
    			{
    				s.push('1');
    			}
    			x = pa;
    		}
    		
    		while(!s.empty())
    		{
    			nodes[i].code += s.top();
    			s.pop();
    		}
    	}// end of hft coding
    	
    	// hft display
    	for(i=0; i<n; i++)
    	{
    		cout<<nodes[i].ch<<" :"<<nodes[i].code<<endl;
    	}
    }
    
    void hft::encode(string s)
    {
    	for(int i=0; i<s.length(); i++)
    	{
    		char c = s[i];
    		for(int j=0; j<n; j++)
    		{
    			if(c == nodes[j].ch)
    			{
    				cout<<nodes[j].code;
    				break;
    			}
    		}
    	}
    	cout<<endl;
    }
    
    void hft::decode(string s)
    {
    	deque<char> q;
    	
    	int x = 2*n-2;
    	for(int i=0; i<s.length(); i++)
    	{
    		if(s[i] == '0')
    		{
    			x = nodes[x].lchild;
    		}
    		else 
    		{
    			x = nodes[x].rchild;
    		}
    		
    		if(nodes[x].lchild==-1 && nodes[x].rchild==-1)
    		{
    			q.push_back(nodes[x].ch);
    			x = 2*n-2;
    		}
    	}
    	
    	if(n<=x && x<2*n-2)
    	{
    		cout<<"error!"<<endl;
    	}
    	else 
    	{
    		while(!q.empty())
    		{
    			cout<<q.front();
    			q.pop_front();
    		}
    		cout<<endl;
    	}
    }
    
    int main()
    {
    	int n;
    	cin>>n;
    	while(n--)
    	{
    		hft t;
    		string s;
    		cin>>s;
    		t.encode(s);
    		cin>>s;
    		t.decode(s);	
    	}
    
    	return 0;
    }
    
    展开全文
  • Huffman编码与解码

    千次阅读 2019-03-18 08:30:45
    编码与解码的思路是通过参考如下网页的,只是自己将不同部分的功能分配到了不同的类中,对集合的使用也是参照的,其使用和自己对代码的修正,大大的调整了编码的效率。 参考:...
    1. 什么是哈夫曼树?
      哈夫曼树是一个完全二叉树,每一叶子节点都有自己的权重,但采用哈夫曼树来携带这些叶子节点时,它是可以达到 叶子节点的权重*叶子节点的深度 是最小的二叉树
    2. 哈夫曼树的用途:
      压缩数据
      例如当进行字符编码时,如果采用utf-8、GBK等进行数据编码,那每一个字符所使用的字节数都是相同的,例如utf-8要么是一个字节要么是两个字节,如果采用哈夫曼编码,使用二叉树的左右分支来存储0、1,可保证每一个叶子节点的编码都不相同,根据一个字符串中每一个字符出现的频率的不同,出现频率越低的字符所在的叶子节点深度越深,查找时花的时间也就相对多一点,出现频率高的叶子节点深度越小,查找是花的时间也就越少,因此使用哈夫曼树编码的时间 字符出现的频率 * 深度 也就最少
    3. 怎么构造哈夫曼树呢?
      ex:“afcacfssaacfaa” (Java版存储结构:链式存储)
    1. 根据每个字符出现的频率进行排序
      在这里插入图片描述

    2)按顺序将两个最小的节点作为叶子节点,小的节点作为左节点,大的作为有节点,相应编码的时候往左为0,往右为1

    在这里插入图片描述

    继续进行下去

    package Data.HuffTree.structure;
    
    import java.util.*;
    
    public class testHuffTree{
        HuffCodeTree tree = new HuffCodeTree();
    
        public static void main(String[] args){
            String str = "cwdav casdc csadcadav ";
            testHuffTree huffcode = new testHuffTree();
            long start = System.currentTimeMillis();
            String encode = huffcode.encode(str);
            System.out.println(System.currentTimeMillis() - start);
            System.out.println(encode);
            System.out.println(huffcode.decode(encode));
        }
    
        public String encode(String str) {
            char[] chars = str.toCharArray();
    
            // 首先整理一遍所有字符 统计他们出现的频率 也就是个字节点的权重
            Map<Character, Integer> charsInfoMap = countCharFrequence(chars);
    
            // 根据权重由小到大的顺序排列各结点 采用用优先级队列
            PriorityQueue<Node> nodeQue = arrangeByFre(charsInfoMap);
    
            // 通过这些节点 来创建哈夫曼树  得到所有字符的编码信息
            buildHuffCodeTree(nodeQue);
    
            //使用对所有的字符进行编码
            return this.tree.encode(chars);
        }
    
        public String decode(String str){
            return this.tree.decode(str);
        }
    
        public Map<Character, Integer> countCharFrequence(char[] chars){
            // 用键值对来存放字符以及其出现的频率
            Map<Character, Integer> charsInfoMap = new Hashtable<Character, Integer>();
            for (char c : chars) {
                Character cs = new Character(c);
                if(charsInfoMap.containsKey(cs)) {
                    charsInfoMap.put(cs, charsInfoMap.get(cs) + 1);
                } else {
                    charsInfoMap.put(cs, new Integer(1));
                }
            }
        }
    
        public PriorityQueue<Node> arrangeByFre(Map<Character, Integer> charsInfoMap){
            //通过优先队列 有序存放节点   当然节点必须重写compareTo方法
            PriorityQueue<Node> nodeQue= new PriorityQueue<>(charsInfoMap.size());
            for (Character key : charsInfoMap.keySet()) {
                Node node = new Node(key.toString(), charsInfoMap.get(key));
                nodeQue.add(node);
                this.tree.addleaf(node);
            }
            return nodeQue;
        }
    
        public void buildHuffCodeTree(PriorityQueue<Node> nodeQue){
            if(nodeQue == null || nodeQue.size() == 0){
                return;
            }
    
            //构造哈夫曼树 小的节点为左子树 大的节点为右
            while(nodeQue.size() > 1){
                Node node1 = nodeQue.poll();
                Node node2 = nodeQue.poll();
                Node parent = new Node(node1.chars + node2.chars,
                    node1.frequence + node2.frequence);
                parent.leftChild = node1;
                parent.rightChild = node2;
    
                node1.parentChild = parent;
                node2.parentChild = parent;
    
                nodeQue.add(parent);
            }
            this.tree.root = nodeQue.poll();
        }
    }
    
    class HuffCodeTree{
        Node root = null;
        /**
         * 所有叶子节点 即所有进行编码的字符所在的节点
         * */
        public List<Node> leaves = new LinkedList<>();
    
        public String encode(char[] chars){
            if(chars.equals("")){return "";}
    
            // 对所有出现的字符进行编码
            Map<Character, String> chara_encoding = new HashMap<>();
            for(Node leaf : this.leaves){
                Node node = leaf;
                String charcode = "";
                while(node != root) {
                    if (node.isLeftChild()) {
                        charcode = '0' + charcode;
                    } else {
                        charcode = '1' + charcode;
                    }
                    node = node.parentChild;
                }
    //            System.out.print(leaf.chars+ " : " + charcode + "  ");
                chara_encoding.put(leaf.chars.charAt(0), charcode);
            }
    
            StringBuffer code = new StringBuffer();
            for(char c : chars){
                code.append(chara_encoding.get(c));
            }
            return code.toString();
        }
    
        public void addleaf(Node e){
            Node node = e;
            this.leaves.add(node);
        }
    
        public void preOrderTra(){
            preOrderTra(root);
        }
    
        //递归 先序遍历
        public void preOrderTra(Node localRoot) {
            if(localRoot != null) {
                localRoot.displayNode();
                preOrderTra(localRoot.leftChild);
                preOrderTra(localRoot.rightChild);
            }
        }
    
        public String decode(String str){
            if(root == null){
                return null;
            }
            String deocodeString = "";
            Node node = root;
            for(char c : str.toCharArray()){
                if(node.leftChild == null && node.rightChild == null){
                    deocodeString += node.chars;
                    node = root;
                }
                if(c == '0'){
                    node = node.leftChild;
                }else if(c == '1') {
                    node = node.rightChild;
                }
            }
            return deocodeString;
        }
    }
    
    class Node implements Comparable<Node>{
        public String chars = "";
        public int frequence;
        public Node leftChild;
        public Node rightChild;
        public Node parentChild;
    
        public Node(String str, int fre){
            this.chars = str;
            this.frequence = fre;
        }
    
        public void displayNode(){
            System.out.println("节点: " + chars + " " + frequence);
        }
        public boolean isLeftChild(){
            return this.parentChild != null && this.parentChild.leftChild == this;
        }
    
        @Override
        public int compareTo(Node o) {
            return this.frequence - o.frequence;
        }
    }
    

    对编码与解码的思路是通过参考如下网页的,只是自己将不同部分的功能分配到了不同的类中,对集合的使用也是参照的,其使用和自己对代码的修正,大大的调整了编码的效率。

    参考:https://blog.csdn.net/kimylrong/article/details/17022319

    1. C版(顺序表存储)

    输入:需编码的n个字符以及对应的权重
    得到:字符对应的01编码

    思路:
    * 使用【2 * n - 1】个节点数组,存放树中所有节点,前n个是叶子节点,也即对应各个字符。
    * 每个节点保存的信息:父节点,左叶子节点,右叶子节点,权重
    * 没有父节点的视作当前字数根节点,没有叶子节点位即为编码字符对应的一个节点,可知当树完全构造成功时,数组最后一个节点即为树的根节点
    * 通过数组保存节点,且在构造哈夫曼树时,不断通过寻找数组中前两个既没有父节点又是最小权重的两个节点,构造下一个子树,会发现因为每次权重最小的节点总是最接近数组最前面,因此保证最后构造的哈夫曼树时最矮的(或者说是最满的)

    // CHuffman.h
    #include <string>
    #include <iostream>
    using namespace std;
    
    class CHuffman
    {
    private:
    	typedef struct {
    		int weight;
    		int parent;
    		int lchild;
    		int rchild;
    	}HuffmanNode, *HuffmanTree;
    	HuffmanNode* nodes;
    	string* codes;
    	int nodeNum;
    	string* chars;
    public:
    	CHuffman();    // 编码的字符, 字符的权重
    	~CHuffman();
    	void PrintAllCodes();
    	void Encode(string codes[], int a[], int n);
    	string Decode(string s);
    private:
    	void CreateHuffTree(int a[], int n);      // 构造哈夫曼树
    	void InitNode(int i, int weight = 0, int parent = -1, int lchild = -1, int rchild = -1); // 初始化一个节点
    	void Select(HuffmanNode* noeds, int range, int& n1, int& n2);   // 选出权重最小的两个节点的序号
    	void GetHuffcodes();    // 计算所有的0, 1哈夫曼编码
    };
    
    // CHuffman.cpp
    #include "CHuffman.h"
    
    CHuffman::CHuffman() {
    	nodes = NULL;
    	nodeNum = NULL;
    	chars = NULL;
    }
    
    void CHuffman::Encode(string codes[], int a[], int n) {
    	chars = codes;
    	CreateHuffTree(a, n);
    	GetHuffcodes();
    }
    
    void CHuffman::CreateHuffTree(int a[], int n) {
    	// 使用数组存放整个树的节点, 共有2 * n - 1  个节点
    	nodeNum = n;
    	int m = 2 * n - 1;     
    	nodes = new HuffmanNode[m];
    
    	// 前n个节点存放叶子节点
    	for (int i = 0; i < n; i++) {
    		InitNode(i, a[i]);
    	}
    
    	for (int i = n; i < m; i++) {
    		InitNode(i, 0, -1);
    	}
    
    	// 构造Huffman树
    	for (int i = n; i < m; i++) {
    		int n1, n2;     // 当前无父节点的所有节点中,权重最小的两个节点的序号
    		Select(nodes, i, n1, n2);
    		nodes[n1].parent = i;
    		nodes[n2].parent = i;
    		InitNode(i, nodes[n1].weight + nodes[n2].weight, -1, n1, n2);
    	}
    }
    
    void CHuffman::GetHuffcodes() {
    	int n = nodeNum;
    	codes = new string[n];
    	for (int i = 0; i < n; i++) {
    		int cur = i;
    		codes[i] = "";
    		int parent;
    		while ((parent = nodes[cur].parent) != -1) {
    			cout << cur << " parent" << parent << ": " << nodes[parent].lchild << " " << nodes[parent].rchild << " \n";
    			if (nodes[parent].lchild == cur) {
    				codes[i] = '0' + codes[i];
    			}
    			else {
    				codes[i] = '1' + codes[i];
    			}
    			cur = parent;
    		}
    	}
    }
    
    void CHuffman::InitNode(int i, int weight, int parent, int lchild, int rchild)
    {
    	nodes[i].weight = weight;
    	nodes[i].parent = parent;
    	nodes[i].lchild = lchild;
    	nodes[i].rchild = rchild;
    }
    
    void CHuffman::Select(HuffmanNode* noeds, int range, int& n1, int& n2) {
    	// 找到两个没有父节点的节点位置
    	n1 = range, n2 = range;
    
    	// 找到最小权重节点
    	for (int i = 0; i < range; i++) {
    		if (nodes[i].parent == -1 ){
    			if (n1 == range) {
    				n1 = i;
    			}
    			else {
    				if (nodes[i].weight < nodes[n1].weight) {
    					n1 = i;
    				}
    			}
    		}
    	}
    
    	// 找到第二小权重节点
    	for (int i = 0; i < range; i++) {
    		if (nodes[i].parent == -1 && i != n1){
    			if (n2 == range) {
    				n2 = i;
    			}
    			else {
    				if ( nodes[i].weight < nodes[n2].weight) {
    					n2 = i;
    				}
    			}
    		}
    	}
    }
    
    
    void CHuffman::PrintAllCodes() {
    	cout << "所有的编码序列为:\n";
    	for (int i = 0; i < nodeNum; i++) {
    		cout << chars[i] << ": " << codes[i] << "\n";
    	}
    }
    
    string CHuffman::Decode(string s) {
    	// 解码01串
    	// 在此出直接将权重作为最后的解码值
    	cout << "解码";
    	int curNode = 2 * nodeNum - 2;
    	if (s.length() < 1) {
    		return "";
    	}
    	string codes = "";
    	for (int i = 0; i < s.length(); i++) {
    		char curChar = s.at(i);
    		if (curChar == '0') {
    			curNode =nodes[curNode].lchild;
    		}
    		else if (curChar == '1') {
    			curNode = nodes[curNode].rchild;
    		}
    		else {
    			exit;
    		}
    		if (nodes[curNode].lchild == -1 && nodes[curNode].rchild == -1) {
    			codes += chars[curNode];
    			curNode = 2 * nodeNum - 2;
    		}
    	}
    	return codes;
    }
    
    CHuffman::~CHuffman() {
    	delete[] nodes;
    	delete[] codes;
    	chars = nullptr;
    }
    
    // main.cpp
    #include "CHuffman.h"
    #include <iostream>
    using namespace std;
    
    int main()
    {
    	string s[] = { "a", "c", "d", "e", "f", "s" };
    	int a[] = { 5, 2, 1, 1, 3, 2 };
    	CHuffman tree;
    	tree.Encode(s, a, 6);
    	tree.PrintAllCodes();
    	cout << tree.Decode("000001010110000011");
    }
    

    代码、以及代码规范还有很多问题,请查看的童鞋多多指正,谢谢!

    展开全文
  • huffman编码与解码【附c++实现代码】

    千次阅读 2020-11-24 14:33:59
    哈夫曼编码(Huffman Coding),又称霍夫曼编码,是一种编码方式,哈夫曼编码是可变字长编码(VLC)的一种。Huffman于1952年提出一种编码方法,该方法完全依据字符出现概率来构造异字头的平均长度最短的码字,有时称之为...

    哈夫曼编码(Huffman Coding),又称霍夫曼编码,是一种编码方式,哈夫曼编码是可变字长编码(VLC)的一种。Huffman于1952年提出一种编码方法,该方法完全依据字符出现概率来构造异字头的平均长度最短的码字,有时称之为最佳编码,一般就叫做Huffman编码(有时也称为霍夫曼编码)。

    哈夫曼编码利用了贪心算法的思想,至于贪心算法,简单地描述下就是,每次都选最好的,这种策略。在处理某些问题时直接使用贪心法,可以获得很好的解决方案。

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

    构建哈夫曼树的算法过程:(简单的来说就是每次把根节点权值最小和次小的二叉树合并)

    构造方式就是从数组中取出两个最小的元素,让他们作为一个新元素的左右节点,在将新元素放入数组中。再取两个最小元素......以此类推。

    直至数组中的元素个数为1的时候,就得到了哈夫曼树。(新的元素是一个节点,放入数组中比较的时候,比较的是里面具体的值)

    这会使得权值大的节点在树的上方,而权值小的节点在树的下方。因此使得整棵树的带权路径(WPL)最小。

    举个例子,看下图,看完这个例子基本上会了哈夫曼树的构建了。

    构建了哈夫曼树之后可以得到字符对应的编码

    我们可以看到字符a对应的编码就是0,字符b对应的编码就是10,字符c对应的编码就是110,字符d对应的编码就是1111

    那么我们如果想对abc进行编码,通过这个哈夫曼树编码就可以得到0101110,这个编码可以被反应解码出来,为什么?因为哈夫曼编码得到的时异字头编码。

    代码效果

    字符权值文件,最后一行数字代表空格的权值

     首先根据字符权值建立对应的haffman树

    然后对要进行编码的文件进行编码,并将编码结果保存到3.txt文件中

     编码结果

    然后可以通过相应的编码和haffman树,译码出对应的内容

     

    获取完整代码

    展开全文
  • json编码与解码

    2017-10-16 10:51:17
    json编码与解码json编码与解码json编码与解码json编码与解码json编码与解码json编码与解码json编码与解码
  • 完美支持中文 base64 编码与解码 目前速度最快 效率最高的编码与解码
  • 里面包括3个文件,一个是编码代码,一个是解码代码,一个是编码解码过程详细解释。简单,可运行。
  • 自适应(动态)哈夫曼编码与解码过程 自定义哈夫曼编码,预先不知道各种符号的出现频率,编码树的初始状态只包含一个叶节点,即NYT(Not Yet Transmitted),NYT是一个逸出码,不同于任何一个将要传送的符号,当一个...

    自适应(动态)哈夫曼编码与解码过程

    自定义哈夫曼编码,预先不知道各种符号的出现频率,编码树的初始状态只包含一个叶节点,即NYT(Not Yet Transmitted),NYT是一个逸出码,不同于任何一个将要传送的符号,当一个尚未包含在编码树中的符号需要被编码时,首先输出NYT的编码,然后跟着符号的原始表达。当解码器解出一个NYT之后,它就知道下面的内容暂时不再是Huffman编码,而是一个从未在编码数据流中出现过的原始符号。当插入一个符号q时,会出现两种情况:

    1. q是第一次出现的字符结点。构造一个新的子树,子树包含NYT符号和新符号两个叶节点,如下图所示。然后判断该子树的父节点是否是是当前权重下编号最大的结点,如果是,直接更新权重即可;否则,将父节点与相同权重的编号最高的结点交换,再更新权重值。
      插入新的字符节点
    2. q不是第一次出现的字符结点。如果q所在节点,是当前节点权重下编号最大的结点,则直接使其当前节点权重及父节点权重加1即可。否则,将当前节点与相同权重的编号最高的结点交换,再更新权重值。

    以字符串“aabbbacc”的编码和解码为例,假设原始共有四类字符(a,b,c,d),规定初始化编码:a-00 b-01 c-10 d-11,此为编码器与解码器双方的约定。

    编码过程:

    1. 初始状态,仅有NYT节点,权重为0
      编码树初始状态
    2. 输入字符a,为新字符,输出编码000。0为NYT编码,00是a的初始编码,此时的huffman树为:
      加入字符a后的编码树
    3. 输入字符a,输出编码1。将a加入到huffman树中,并进行调整。
      加入字符a后的编码树
    4. 输入字符b,为新字符,输出编码001。0是NYT编码,01是b的初始编码。
      输入字符b后的编码树
    5. 输入字符b,输出编码01。将字符b加入到huffman树中,并进行调整。
      输入字符b后的编码树
    6. 输入字符b,输出编码01。将字符b加入到huffman树中,注意此时b节点不是当前权重值下编号最大的节点,需要进行节点的交换操作,即节点(2)与节点(4)交换。
      输入字符b后的编码树
    7. 输入字符a,输出编码01,将a加入到huffman树中。
      输入字符a后的编码树
    8. 输入字符c,为新字符,输入编码0010。00是NYT编码,10是c的初始编码。该子树的父节点(5)不是当前权重下编号最大的节点,所以节点(5)与节点(6)交换,并更新权重值。
      输入字符c后的编码树
    9. 输入字符c,输出编码101,将字符c加入到huffman树中。
      输入字符c后的编码树
      综上所述,字符串“aabbbacc”动态哈夫曼编码的结果为00010010101010010101

    解码过程:

    由于自适应 Huffman编码算法采用了先编码,后调整编码树的方案,相应的解码算法比较简单。解码算法也使用仅有唯一的NYT节点的编码树作为初始状态,然后根据Huffman编码数据流,对符号进行还原。每次处理完一个符号,就使用这个符号调整编码树。这样,在每一次输入新的符号之前,Huffman树都处于与进行编码时使用的Huffman树完全相同的状态,保证了解码的正确性。

    具体的C语言代码实现:https://download.csdn.net/download/weixin_43838265/19121832

    展开全文
  • 遗传算法的编码方法各种各样,但二进制串编码方式是最经典的一种,那么它的编码解码该如何进行呢?或许本博客能给你一个具有参考价值的答案。 编码 经典遗传算法中使用“染色体”来代指个体,它由二进制串组成,...
  • 哈夫曼树建立、编码解码 1、哈夫曼树的建立 Huffman树是根据元素的权重建立的,权重较小的离根结点较远,而权重较大的离根结点较近,从而使得整个Huffman树有着最小的带权路径长度。Huffman树的具体特性请参考...
  • java中的编码与解码

    万次阅读 2018-05-17 21:05:08
    编码表概述和常见的编码表 概述:有字符及其对应的数值组成的一张表 常见的编码表 ASCII:美国标准信息交换表 ISO8859-1:拉丁码表,欧洲码表 GB2312:中国的中文编码表 GBK:中国的中文编码表升级 GB18030:GBK的...
  • 图像编码与解码

    千次阅读 2018-06-13 17:46:41
    //图像数据编码入dataSrc,第一个参数指定图片格式 imencode(".jpg", imgSrc, dataSrc); //解码图像数据dataSrc入图像 Mat imgDst = imdecode(dataSrc, CV_LOAD_IMAGE_COLOR); imshow("解码图像", imgDst); ...
  • 红外遥控编码与解码

    千次阅读 2020-05-03 10:10:45
    随着家用电器、视听产品的普及,红外线遥控器已被广泛使用在各种类型的家电... 其中发射部分主要包括键盘矩阵、编码调制、红外发射管;接收部分包括光、电信号的转换以及放大、解调、解码电路。举例来说,通常我...
  • 用LZW压缩算法实现的编码与解码

    热门讨论 2009-12-30 17:42:50
    压缩文件有两个源码文件LZWCode.cpp和LZWDecode.cpp可以实现LZW的编码与解码,并有简要的使用说明文档。
  • Utf-8编码与解码(vb6代码) 用VB做爬虫时遇到的乱码问题,编解码方式不对造成,用这个方法使各种编码方式之间互相转化
  • C++ jpeg图像编码与解码
  • 航信汉字的编码与解码编码便于使自己的pid进行汉字传输, 航信汉字编码与解码,eterm汉字编码与解码,汉字编码问题
  • JSON编码与解码

    万次阅读 2018-04-30 05:06:20
    1: JSON编码解码的一个开源的C库; 2: 编译mjson到项目工程中; mjson资源下载 参考文档 JSON编码 1: mjson编码步骤; 1> 创建一个JSON对象: json_new_string 创建一个字符串对象; json_...
  • js 字符串编码与解码

    千次阅读 2019-07-30 15:27:35
    编码有三种 1、escape(对应解码unescape) 定义:escape() 对字符串进行编码。 注意: 该方法不会对 ASCII 字母和数字进行编码,也不会对下面这些 ASCII 标点符号进行编码: * @ - _ + . / 。其他所有的字符都会...
  • Matlab技术的AMI编码解码的实现
  • javascript UTF-8的编码与解码

    千次阅读 2020-09-09 16:03:04
    JavaScript本身可通过charCodeAt方法得到一个字符的Unicode编码,并通过fromCharCode方法将Unicode编码转换成对应字符。...不过有一个简便的办法来实现UTF-8的编码与解码。Web要求URL的查询字符串采用UTF...
  • socket介绍--数据的编码与解码

    千次阅读 2018-08-28 10:23:36
    strict:表示严格按照指定编解码方式进行编码解码,如果编解码不成功则抛出异常 ignore:表示忽略编解码不成功的字符,如果编解码不成功程序不会抛出异常 口诀:用什么编码就用什么解码
  • 本文详细的介绍了RS编码解码,并通过MATLAB仿真
  • js中文转Unicode编码与解码

    千次阅读 2019-02-11 11:31:00
    中文转为unicode 编码: function encodeUnicode(str) { var res = []; for (var i = 0; i < str.length; i++) { res[i] = ( "00" + str.charCodeAt(i).toString(16) ).slice(-4); } return "\\u".....

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 354,293
精华内容 141,717
关键字:

编码与解码