实验八 二叉树的应用(第11周)

实验目的:

  掌握赫夫曼二叉树的建立及赫夫曼编码的生成。

实验内容与要求:

  根据给定的n个权值生成赫夫曼二叉树,输出赫夫曼编码及进行译码。

#include<iostream>
#include<vector>
#include<stack>
using namespace std;
const int MAX = 9999;

class HuffmanTree {
private:
	struct HTnode {
		char name;				//节点名称
		unsigned int weight;		//权重
		unsigned int parent, lchild, rchild;	//双亲、左右孩子节点


		//初始化
		HTnode() {
			name = 'n';
			weight = 0;
			parent = 0; lchild = 0; rchild = 0;
		}
	};
	vector<HTnode>hu;
	

public:
	void accept(int n);				//接受给定的n个权值
	void select(int& a, int& b);	//找到hu中权值最小且无双亲的两个节点,返回值a,b
	void create();					//创建赫夫曼树
	void print(int n,string s);				//输出赫夫曼编码
	void code();				//进行译码
};


void HuffmanTree::accept(int n)
{	
	for (int i = 0; i < n; i++) {
		HTnode p;
		cout << "输入节点名称及权值(例如:A 1):";
		cin >> p.name;
		cin >> p.weight;
		hu.push_back(p);
	}
}

void HuffmanTree::select(int& a, int& b)
{
	
	vector<HTnode>v;
	//排除所有双亲不为0的节点
	for (unsigned i = 0; i < hu.size(); i++) {
		if (hu[i].parent == 0)v.push_back(hu[i]);
		else {
			HTnode p;
			p.weight = MAX;
			v.push_back(p);
		}
	}
	//找到权最小的两个节点
	unsigned int tmp = MAX;
	for (unsigned i = 0; i < v.size(); i++) {
		if (v[i].weight < tmp) {
			a = i;
			tmp = v[i].weight;
		}
	}
	tmp = MAX; 
	for (unsigned i = 0; i < v.size(); i++) {
		if(i!=a)
		if (v[i].weight < tmp) {
			b = i;
			tmp = v[i].weight;
		}
	
	}
}

void HuffmanTree::create()
{	
	unsigned int s = 2*this->hu.size()-1;
	int i, j;
	while (this->hu.size() != s) {
		select(i, j);
		//将这两个节点合并成一棵二叉树
		HTnode p;
		p.name = hu[i].name + hu[j].name;
		p.weight = hu[i].weight + hu[j].weight;	
		if (i < j) {
			p.lchild = j;
			p.rchild = i;
		}
		else {
			p.lchild = i;
			p.rchild = j;
		}
		hu.push_back(p);
		hu[i].parent = hu.size() - 1;
		hu[j].parent = hu.size() - 1;
		
	}
}

void HuffmanTree::print(int n,string s)
{
	unsigned int i = 0, j = 0;
	stack<char>st;		//利用栈输出编码信息
	for (unsigned int x= 0; x < s.size(); x++) {
		for (unsigned int y = 0; y < n; y++) {
			if (s[x] == hu[y].name) {
				j = y;
				i = y;
			}
		}
		//求每个字符的赫夫曼编码
		while (hu[j].parent != 0) {
			if (j == hu[hu[j].parent].lchild) st.push('0');
			if (j == hu[hu[j].parent].rchild) st.push('1');
			j = hu[j].parent;
		}
		//输出编码
		while (!st.empty()) {
			cout << st.top();
			st.pop();
		}
	}
}

void HuffmanTree::code()
{
	cout <<endl<< "输入编码找到相应节点,以#结尾(例:000#):";
	unsigned int j = hu.size()-1;
	int a = 0;
	string s;
	cin >> s;
	for(unsigned i=0;i<s.size();i++) {
		if (s[i] == '0' && (hu[j].lchild != 0|| hu[j].rchild != 0)) j = hu[j].lchild;
		else if (s[i] == '1' && (hu[j].lchild != 0 || hu[j].rchild != 0))j = hu[j].rchild;
		else {
			cout << hu[j].name;
			j = hu.size() - 1;
			if(s[i]!='#')i--;
		}
	}
}


int main() {
	HuffmanTree T;
	int n; string s;
	cout << "输入权值个数:";
	cin >> n;
	cout << endl;
	if (n < 2) {
		cout << "error";
	}
	else {
		T.accept(n);
		T.create();
		cout << endl;
		cout << "输入一串字符:";
		cin >> s;
		T.print(n, s);
		cout << endl;
		T.code();
		cout << endl;
	}
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值