自适应Huffman编码

自适应Huffman编码,可用初始编码表(数字音视频技术,实验二)

如果你已经理解了 自适应Huffman编码 ,那么你不应该浪费时间在无聊的实验上

实验目的

1、深入掌握自适应Huffman编码的原理
2、掌握自适应Huffman编码算法的实现过程
3、掌握和熟悉利用编程语言实现自适应Huffman编码器和解码器

实验要求

1、实现编码器,对输入字符给出相应的编码结果;
2、实现解码器,对步骤1中的编码结果进行解码;
3、请使用初始编码表如下:
在这里插入图片描述
4、对字符串ABBCADAD进行编码;
5、截图显示编码中间结果,并保证最终解码结果正确;
6、编辑程序说明文档。

实验步骤

附实验代码及说明文档

实验体会

记录实验过程中碰到的问题及解决方法、最终实验结果。

实现代码:

cpp文件,main函数里包含初始编码表 代码片.

#include "huffmanTree.h"
#include <map>
map<char, string> initCode;


BinaryTree::BinaryTree(int num, int weight)
{
	p_root = new Node(nullptr, nullptr, nullptr);
	p_root->num = num; //节点的序号
	p_root->weight = weight;  //节点的权重值
}


BinaryTree::~BinaryTree()
{
	deleteNode(p_root);
}


bool BinaryTree::swap(Node * p_nodeA, Node * p_nodeB)
{
	if (p_nodeA == nullptr || p_nodeB == nullptr || p_nodeA == p_nodeB)
		return false;
	Node *pTemp;
	if (getBrotherState(p_nodeA) == LeftChild) { //如果A节点是左孩子
		if (getBrotherState(p_nodeB) == LeftChild) { // 如果B节点是左孩子
			pTemp = p_nodeA->p_parent->p_left;
			p_nodeA->p_parent->p_left = p_nodeB->p_parent->p_left;
			p_nodeB->p_parent->p_left = pTemp;
		}
		else {
			pTemp = p_nodeA->p_parent->p_left;
			p_nodeA->p_parent->p_left = p_nodeB->p_parent->p_right;
			p_nodeB->p_parent->p_right = pTemp;
		}
	}
	else {
		if (getBrotherState(p_nodeB) == LeftChild) {
			pTemp = p_nodeA->p_parent->p_right;
			p_nodeA->p_parent->p_right = p_nodeB->p_parent->p_left;
			p_nodeB->p_parent->p_left = pTemp;
		}
		else {
			pTemp = p_nodeA->p_parent->p_right;
			p_nodeA->p_parent->p_right = p_nodeB->p_parent->p_right;
			p_nodeB->p_parent->p_right = pTemp;
		}
	}

	pTemp = p_nodeA->p_parent;
	p_nodeA->p_parent = p_nodeB->p_parent;
	p_nodeB->p_parent = pTemp;
	return true;

}


bool BinaryTree::addNode(Node * p_parent, Node * p_child, Brother brotherState)
{
	if (p_parent == nullptr || p_child == nullptr)
		return false;
	if (brotherState == LeftChild) { 
		if (p_parent->p_left != nullptr) {
			std::cout << "error:left child exist!" << std::endl;
			return false;//如果父节点有左孩子,则不能添加到左孩子位置
		}
		p_parent->p_left = p_child;//否则可以添加
	}
	else if (brotherState == RightChild) { 
		if (p_parent->p_right != nullptr) {
			std::cout << "error:right child exist!" << std::endl;
			return false;//如果父节点有右孩子,则不能添加到右孩子位置
		}
		p_parent->p_right = p_child;//否则可以添加
	}
	else {
		std::cout << "error:brotherState is wrong!" << std::endl;//读取位置信息错误
		return false;
	}
	p_child->p_parent = p_parent;
	return true;
}


bool BinaryTree::isAncestor(Node * p_nodeChild, Node * p_nodeAncestor)
{
	while (p_nodeChild != p_root) {
		if (p_nodeChild == p_nodeAncestor) {
			return true;
		}
		else {
			p_nodeChild = p_nodeChild->p_parent;
		}
	}
	return false;
}


void BinaryTree::deleteNode(Node *p_node)
{
	if (p_node->p_left != nullptr) {
		deleteNode(p_node->p_left);
	}
	if (p_node->p_right != nullptr) {
		deleteNode(p_node->p_right);
	}
	delete p_node;
}


BinaryTree::Brother BinaryTree::getBrotherState(Node *p_node)
{
	if (p_node->p_parent->p_left == p_node) {
		return LeftChild;
	}
	else {
		return RightChild;
	}
}


HuffmanTree::HuffmanTree() :tree(0, 0)
{

	sum = 1;
}


string HuffmanTree::getHuffmanCode(Node *p_n)
{
	std::string huffmanCode = "";
	std::stack<Node *> stack;
	std::deque<char> code;
	if (p_n == tree.getRoot())
		return "0";

	while (p_n != tree.getRoot()) {
		if (tree.getBrotherState(p_n) == tree.LeftChild) {
			code.push_back('0');
		}
		else {
			code.push_back('1');
		}
		p_n = p_n->p_parent;
	}
	while (!code.empty()) {
		huffmanCode += code.back();
		code.pop_back();
	}
	



	return huffmanCode;
}


Node * HuffmanTree::findLarge(Node *p_node)
{
	std::stack<Node *> stack;
	Node *p = tree.getRoot();
	Node *large = p;
	while (p || !stack.empty()) {
		if (p != nullptr) {
			stack.push(p);
			if (p->weight == p_node->weight) {
				//如果large不在同权重下,则置large为p
				if (large->weight != p->weight) {
					large = p;
				}
				//同权重下的large比p小,则置large为p
				else if (large->num > p->num) {
					large = p;
				}
			}
			p = p->p_left;
		}
		else {
			p = stack.top();
			stack.pop();
			p = p->p_right;
		}
	}

	if (large == tree.getRoot()) {
		return p_node;
	}
	return large;
}


void HuffmanTree::encode( string input)
{


	char cbuffer;
	Node *nyt = tree.getRoot();
	bool exist = false;
	for (int i = 0; i < input.length(); i++) { 

		cbuffer = input[i];		
		exist = false;
		string code;


		auto existNode = buffers.begin();	
		for (existNode; existNode != buffers.end(); existNode++) {
			if (existNode->key == cbuffer) {
				code = existNode->value;
				exist = true;
				cout << cbuffer << " 在树中存在,编码为: " << existNode->value << endl; 
				break;
			}
		}



		if (exist) 
		{ 

			Node *root = existNode->p;
			weightAdd(root);

		}
		else 
		{
			
			Node *c = new Node(nullptr, nullptr, nyt);
			c->num = sum++;
			c->weight = 1;

			Node *NYT = new Node(nullptr, nullptr, nyt);
			NYT->num = sum++;
			NYT->weight = 0;

			cout << "\n NYT:" << getHuffmanCode(nyt) << endl;

			tree.addNode(nyt, NYT, BinaryTree::LeftChild);
			tree.addNode(nyt, c, BinaryTree::RightChild);
			nyt->weight = 1;

			
			cout << cbuffer << "首次出现,编码为:"<< initCode.at(cbuffer) << endl;
			
			charMap* new_cm = new charMap();
			new_cm->key = cbuffer;
			new_cm->p = nyt->p_right;
			new_cm->value = getHuffmanCode(nyt->p_right);
			buffers.push_back(*new_cm);

			Node *root = nyt->p_parent;
			weightAdd(root);
			
			nyt = nyt->p_left;
			
		}

	}
	
}



void HuffmanTree::weightAdd(Node * p_node)
{
	while (p_node != nullptr) {
		Node* large = findLarge(p_node);
		if (large != p_node && !tree.isAncestor(p_node, large)) { 			
			tree.swap(large, p_node);
			int temp;
			temp = large->num;
			large->num = p_node->num;
			p_node->num = temp;
			for (auto iterator = buffers.begin(); iterator != buffers.end(); iterator++) {
				iterator->value = getHuffmanCode(iterator->p);
			}
		}
		p_node->weight++;		
		p_node = p_node->p_parent;
	}
}



void HuffmanTree::decode(string input)
{
	Node *nyt = tree.getRoot();
	int p = 0;
	int l = 1;
	string temp;
	bool exit = false;
	for (;p+l<= input.length();)
	{
		exit = false;
		temp = input.substr(p, l);
		cout << "\n循环: " << temp ;
		
		//如果是NYT,说明有新的
		if (temp == getHuffmanCode(nyt)) 
		{
			p+=l;
			l = 5;
			temp = input.substr(p, l);
			
			//在字典中寻找对应值
			for (auto iter = initCode.begin(); iter != initCode.end(); ++iter) {
				string cur = iter->second;
				if (cur == temp)
				{
					//找到了就加新的

					cout << "      新码的:" << iter->first << endl;

					Node *c = new Node(nullptr, nullptr, nyt);
					c->num = sum++;
					c->weight = 1;

					Node *NYT = new Node(nullptr, nullptr, nyt);
					NYT->num = sum++;
					NYT->weight = 0;

					

					tree.addNode(nyt, NYT, BinaryTree::LeftChild);
					tree.addNode(nyt, c, BinaryTree::RightChild);
					nyt->weight = 1;


					charMap* new_cm = new charMap();
					new_cm->key = iter->first;
					new_cm->p = nyt->p_right;
					new_cm->value = getHuffmanCode(nyt->p_right);
					buffers.push_back(*new_cm);

					//依次增加权重
					Node *root = nyt->p_parent;
					weightAdd(root);

					//设置新的nyt节点为原nyt节点的左孩子
					nyt = nyt->p_left;

				}
				
			}
			p += l;
			l = 1;
		
			exit = true;
		}
		else//如果不是NYT,就在树里面找
		{
			auto existNode = buffers.begin();
			for (existNode; existNode != buffers.end(); existNode++) {
				if (existNode->value == temp) 
				{
					//找到
					cout  << "     在树中存在,为: " << existNode->key << endl;
					Node *root = existNode->p;
					weightAdd(root);

					p += l;
					l = 1;
					exit = true;
					break;
				}
			}
		}

		//如果即不再树中也不在字典中,l++
		if(!exit)
			l++;




	}

}


//主函数程序
int main()
{


	HuffmanTree huff;
	
	//这个字典是初始编码表
	initCode['A'] = "00001";
	initCode['B'] = "00010";
	initCode['C'] = "00011";
	initCode['D'] = "00100";




	string input = "ABBCADAD";
	huff.encode(input);//进行编码的函数



	//以下是解码函数
	HuffmanTree dhuff;
	dhuff.decode("0000010000100100000110110000100111001");
	system("PAUSE");
	return 0;
}

.h头文件 代码片.

#pragma once
#include <fstream>
#include<iostream>
#include<vector>
#include<queue>
#include<stack>
#include<string>

using namespace std;



struct Node {
	int weight; 
	int num;  
	Node* p_left; 
	Node* p_right;  
	Node* p_parent; 
	Node(Node* p_left, Node* p_right, Node* p_parent) : p_left(p_left), p_right(p_right), p_parent(p_parent) {};
};


class BinaryTree
{
public:

	enum Brother { LeftChild, RightChild };
	BinaryTree(int num = 0, int weight = 0);
	~BinaryTree();
	bool swap(Node* p_nodeA, Node* p_nodeB);
	bool addNode(Node* p_parent, Node* p_child, Brother brotherState);
	Node* findNode(string in);
	void deleteNode(Node *p_node);
	Node* getRoot() { return p_root; }

	Brother getBrotherState(Node *p_node);
	bool isAncestor(Node* p_nodeChild, Node* p_nodeAncestor);
private:
	Node *p_root;

};



class HuffmanTree
{
public:
	int sum;
	HuffmanTree();


	void encode(string input);
	void weightAdd(Node* p_node);
	void decode(string input);
	
	BinaryTree tree;


	struct charMap {
		char key;
		std::string value;
		Node* p;
	};
	vector<charMap> buffers;

	string getHuffmanCode(Node *p);
	Node * findLarge(Node *);

	
}; 

  • 源代码修改自https://blog.csdn.net/qq_36533706/article/details/80381457?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522163819021616780366596114%2522%252C%2522scm%2522%253A%252220140713.130102334…%2522%257D&request_id=163819021616780366596114&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2allsobaiduend~default-2-80381457.first_rank_v2_pc_rank_v29&utm_term=%E8%87%AA%E9%80%82%E5%BA%94Huffman%E7%BC%96%E7%A0%81&spm=1018.2226.3001.4187
  • 7
    点赞
  • 50
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
自适应霍夫曼编码的C++版本简单实现 class AdaptiveTree { public: AdaptiveTree(int rootNum); AdaptiveTree(int rootNum, string str); void swap(int first, int second); // swap two nodes of the tree void initalCode(); // initializing the data string char2code(unsigned char letter); // locate the character in the tree with its corresponding binary string and return the string string char2binary(unsigned char letter); // translating the character to the 8-bit binary string unsigned char binary2char(string bin); // translating the binary string: bin to the corresponding character int spawn(unsigned char letter); // add a new character to the original tree void updateTree(unsigned char newchar); // update the tree int highestInBlock(int count); // return the highest node to be exchanged void setString(string str); // string decodingStr() const; void encoding(); string decoding(); unsigned char code2char(string bincode); static int size(); string binStr() const; // return the binary string of string: tempString private: void run(); int findchar(unsigned char letter ); // locate the letter in the tree string tempString; //temp string to be encoded needed to be stored here string deStr;// used for storing the decoding string string bin; // used for storing the result of encoding process /* Adaptive Tree data members */ HuffmanTree *tree; int root; /* Adaptive Tree constants */ static int ALPH_SIZE; // size of the alphabet static unsigned char none; // not a unsigned character static unsigned char NYT; // Not Yet transmitted code };

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值