哈夫曼树的实现

原创 2013年12月04日 20:26:30

输入字符集以及权值,建立哈夫曼树进行一系列操作;其中建立哈夫曼树,以及编码部分参考了百度百科;

#include <iostream>
#include <fstream>
#include <cstdlib>
using namespace std;

const int MAXVALUE = 99999; //初始设定的权值最大值
const int MAXBIT = 10; //初始设定的最大编码位数
const int MAXN = 1000; //初始设定的最大结点个数

struct HaffNode //哈夫曼树的结点结构
{
	int weight; //权值
	int flag; //标记
	int parent; //双亲结点下标
	int leftChild; //左孩子下标
	int rightChild; //右孩子下标
};

struct Code //存放哈夫曼编码的数据元素结构
{
	int bit[MAXBIT]; //数组
	int start; //编码的起始下标
	int weight; //字符的权值
};

void Menu();
void Haffman(int weight[], int n, HaffNode haffTree[]);//建树
void HaffmanCode(HaffNode haffTree[], int n, Code haffCode[]);//生成哈夫曼编码
void Coding(char str[], char s[], int n, Code code[]);
void DeCoding(int n, char s[], HaffNode hafftree[]);
void ReadFile(char s[]);
void PreOrder(HaffNode haffTree[], int n);
void InOrder(HaffNode haffTree[], int n);

int main()
{
	int i, weight[MAXN], len;
	char strChar[MAXN], c;
	bool flag = true;
	HaffNode *hafftree;
	Code *haffcode;

	Menu();
	while(flag)
	{	
		cout << "please input:";
		cin >> c;
		switch(c)
		{
			case 'B':
			{
				cout << "please input string:";
				cin>>strChar;
				len = strlen(strChar);
				cout << "please input weight:";
				for(i=0; i<len; i++)
					cin >> weight[i];	
				hafftree = new HaffNode[2*len-1];
				Haffman(weight, len, hafftree);
			}
			break;

			case 'E':
			{
				haffcode = new Code[len];
				HaffmanCode(hafftree, len, haffcode);
			}
			break;

			case 'T':
			{
				PreOrder(hafftree, 2*len-2);
				cout << endl;
				InOrder(hafftree, 2*len-2);
				cout << endl;
			}
			break;

			case 'C':
			{
				char strInput[MAXN];
				cout << "please input string:";
				cin >> strInput;
				Coding(strInput, strChar, len, haffcode);
			}
			break;

			case 'D':
			{
				DeCoding(len, strChar, hafftree);
			}
			break;

			case 'P':
			{
				ReadFile("textfile.txt");
				ReadFile("codefile.txt");
				ReadFile("result.txt");
			}
			break;

			case 'X':
			{
				flag = false;
			}
			break;

			case 'S':
			{
				Menu();
			}
			break;

			default:
				break;
		}
	}
	return 0;
}

void Menu()
{
	cout<<"********************************************************************"<<endl;
	cout<<"* B—建树:   读入字符集和各字符频度,建立哈夫曼树。*****************"<<endl;
	cout<<"********************************************************************"<<endl;
	cout<<"* T—遍历:   先序和中序遍历二叉树。                *****************"<<endl;
	cout<<"********************************************************************"<<endl;
	cout<<"* E—生成编码: 根据已建成的哈夫曼树,产生各字符的哈夫曼编码。*******"<<endl;
	cout<<"********************************************************************"<<endl;
	cout<<"* C—编码:   输入由字符集中字符串组成的任意字符串,利用已生成的 ****"<<endl;
	cout<<"*            哈夫曼编码,显示编码结果,并将输入的字符串及其编码  ****"<<endl;
	cout<<"*            结果分别保存在磁盘文件textfile.txt和codefile.txt中。***"<<endl;
	cout<<"********************************************************************"<<endl;
	cout<<"* D—译码:   读入codefile.txt,利用建议建成的哈夫曼树进行译码,******"<<endl;
	cout<<"*            并将译码结果放入磁盘文件result.txt。             ******"<<endl;
	cout<<"********************************************************************"<<endl;
	cout<<"* P—打印:   屏幕显示文件textfile.txt、codefile.txt和result.txt。***"<<endl;
	cout<<"********************************************************************"<<endl;
	cout<<"* X—退出。                           ******************************"<<endl;
	cout<<"********************************************************************"<<endl;
}

void Haffman(int weight[], int n, HaffNode haffTree[])
//建立叶结点个数为n权值为weight的哈夫曼树haffTree
{
	int j, m1, m2, x1, x2;
	//哈夫曼树haffTree初始化。n个叶结点的哈夫曼树共有2n-1个结点
	for(int i = 0; i < 2 * n - 1 ; i++)
	{
		if(i < n)
			haffTree[i].weight = weight[i];
		else 
			haffTree[i].weight = 0;
		haffTree[i].parent = 0;
		haffTree[i].flag = 0;
		haffTree[i].leftChild = -1;
		haffTree[i].rightChild = -1;
	}
	//构造哈夫曼树haffTree的n-1个非叶结点
	for(i = 0;i < n-1;i++)
	{
		m1 = m2 = MAXVALUE;
		x1 = x2 = 0;
		for(j = 0; j < n+i;j++)
		{
			if (haffTree[j].weight < m1 && haffTree[j].flag == 0)
			{
				m2 = m1;
				x2 = x1;
				m1 = haffTree[j].weight;
				x1 = j;
			}
			else if(haffTree[j].weight < m2 && haffTree[j].flag == 0)
			{
				m2 = haffTree[j].weight;
				x2 = j;
			}
		}
	//将找出的两棵权值最小的子树合并为一棵子树
		haffTree[x1].parent = n + i;
		haffTree[x2].parent = n + i;
		haffTree[x1].flag = 1;
		haffTree[x2].flag = 1;
		haffTree[n+i].weight = haffTree[x1].weight + haffTree[x2].weight;
		haffTree[n+i].leftChild = x1;
		haffTree[n+i].rightChild = x2;
	}
}

void HaffmanCode(HaffNode haffTree[], int n, Code haffCode[])
//由n个结点的哈夫曼树haffTree构造哈夫曼编码haffCode
{
	Code *cd = new Code;
	int child, parent;
	//求n个叶结点的哈夫曼编码
	for(int i = 0; i < n; i++)
	{
		cd->start = n-1; //不等长编码的最后一位为n-1
		cd->weight = haffTree[i].weight; //取得编码对应权值的字符
		child = i;
		parent = haffTree[child].parent;
	//由叶结点向上直到根结点
		while(parent != 0)
		{
			if(haffTree[parent].leftChild == child)
			cd->bit[cd->start] = 0; //左孩子结点编码0
			else
			cd->bit[cd->start] = 1;//右孩子结点编码1
			cd->start--;
			child = parent;
			parent = haffTree[child].parent;
		}
	//保存叶结点的编码和不等长编码的起始位
		for(int j = cd->start+1; j < n; j++)
			haffCode[i].bit[j] = cd->bit[j];
		haffCode[i].start = cd->start;
		haffCode[i].weight = cd->weight; //保存编码对应的权值
	}
}

void Coding(char str[], char s[], int n, Code code[])
{
	ofstream outf("textfile.txt");
	int len = strlen(str);

	if(!outf)
	{
		cout << "cannot open the file\n";
		return ;
	}

	outf << str;
	outf << endl;
	outf.close();

	ofstream outfc("codefile.txt");
	if(!outfc)
	{
		cout << "cannot open the file\n";
		return ;
	}
	for(int i=0; i<len; i++)
	{
		for(int j=0; j<n; j++)
		{	
			if(str[i] == s[j])
				break;
		}
		for(int k=code[j].start+1; k<n; k++)
			outfc << code[j].bit[k];
	}
	outfc << endl;
	outfc.close();
}

void DeCoding(int n, char s[], HaffNode hafftree[])
{
	ifstream inf("codefile.txt");
	char str[MAXN];
	inf >> str;

	ofstream outf("result.txt");
	int len = strlen(str);

	int j = 2 * n - 2;
	for(int i=0; i<len; i++)
	{
		if('0' == str[i])
		{
			if(0 <= hafftree[j].leftChild && hafftree[j].leftChild < n)
			{
				outf << s[hafftree[j].leftChild];
				j = 2 * n - 2;
			}
			else
				j = hafftree[j].leftChild;
		}
		else
		{
			if(0 <= hafftree[j].rightChild && hafftree[j].rightChild < n)
			{
				outf << s[hafftree[j].rightChild];
				j = 2 * n - 2;
			}
			else
				j = hafftree[j].rightChild;
		}
	}

	inf.close();
	outf.close();
}

void ReadFile(char s[])
{
	ifstream inf(s);
	char str[MAXN];
	inf >> str;
	cout << s << ":" << str << endl;
	inf.close();
}

void PreOrder(HaffNode haffTree[], int n)
{
	if(n > -1)
	{
		cout << haffTree[n].weight << " ";
		PreOrder(haffTree, haffTree[n].leftChild);
		PreOrder(haffTree, haffTree[n].rightChild);
	}
}

void InOrder(HaffNode haffTree[], int n)
{
	if(n > -1)
	{
		InOrder(haffTree, haffTree[n].leftChild);
		cout << haffTree[n].weight << " ";
		InOrder(haffTree, haffTree[n].rightChild);
	}
}


哈夫曼树的c++实现

huffman 树称为最优二叉树,用其来对字符编码是一种比较好的选择,huffman树的实现也比较简单,构造huffman树的思想就是每次从序列中取出权值最小的两个,然后构造出一个树,然再去构造,一直...
  • hujian_
  • hujian_
  • 2016年05月24日 11:21
  • 1412

哈夫曼树-贪心算法的应用实例

/* *哈夫曼编码-链式结构 * *功能实现: * 源文件字符权值确认操作 * 哈夫曼树的建立操作 * 字符字典的建立操作 * 源文件转码操作操作 * 二进制文件译码操作 * 文件输出操作...
  • a915650754
  • a915650754
  • 2014年12月07日 23:11
  • 1401

哈夫曼树及一种java实现

最优二叉树,也称哈夫曼(Haffman)树,是指对于一组带有确定权值的叶结点,构造的具有最小带权路径长度的二叉树。 那么什么是二叉树的带权路径长度呢? 在前面我们介绍过路径和结点的路径长度的概念,...
  • Allenalex
  • Allenalex
  • 2016年03月23日 20:54
  • 969

数据结构(15)--哈夫曼树以及哈夫曼编码的实现

1.哈夫曼树     假设有n个权值{w1, w2, ..., wn},试构造一棵含有n个叶子结点的二叉树,每个叶子节点带权威wi,则其中带权路径长度WPL最小的二叉树叫做最优二叉树或者哈夫曼树。  ...
  • u010366748
  • u010366748
  • 2016年03月01日 17:28
  • 6254

树结构(四) - 哈夫曼树的原理与实现

一、哈夫曼树的介绍 Huffman Tree,中文名是哈夫曼树或霍夫曼树,它是最优二叉树。 定义:给定n个权值作为n个叶子结点,构造一棵二叉树,若树的带权路径长度达到最小,则这棵树被称为哈夫曼树。 这...
  • leicool_518
  • leicool_518
  • 2015年01月13日 13:24
  • 2006

哈夫曼树的代码实现

定义 哈夫曼树,又称最优树,是一类带权路径长度最短的树。 树的带权路径长度,是树中所有叶子 节点的带权路径长度之和。通常记做WPL=W1*L1+W2*L2+...+Wn*Ln。 例如: 节...
  • cqnuztq
  • cqnuztq
  • 2013年05月13日 10:20
  • 20280

Python使用优先队列,树结构实现哈夫曼算法(哈夫曼树)

对于哈夫曼树就不做介绍了,直接进入正题。 本篇使用简单的结点创建导入优先队列中进行处理然后将树根地址传入二叉树方法中,通过广度遍历实现查询。class node:结点创建,left指向左子结点地址,...
  • cube_ice
  • cube_ice
  • 2017年12月13日 20:04
  • 193

哈夫曼树的实现及其实例分析

定义给定n个权值作为n个叶子结点,构造一棵二叉树,若带权路径长度达到最小,称这样的二叉树为最优二叉树,也称为哈夫曼树(Huffman Tree)。...
  • ldx19980108
  • ldx19980108
  • 2017年11月20日 22:56
  • 647

哈夫曼树编码C语言实现

实现哈夫曼树编码的算法可分为两大部分: (1)构造哈夫曼树; (2)在哈夫曼树上求叶结点的编码; 哈夫曼树构造算法: (1)由给定的n个权值构造n棵只有一个叶结点的二叉树,从而得到一个二叉树的集合F=...
  • qq_29187355
  • qq_29187355
  • 2017年05月06日 01:46
  • 861

哈夫曼树数据机构的建立及哈夫曼编码与解码的C++实现

纠结了两天,终于解决了这个问题,分享给大家自己的思路。 将一组无序数列建立最小堆,从最小堆中弹出两个最小的元素作为左右儿子其和为父节点构建一个树,将父节点加入最小堆,再次调用以上方法重复构建树,最终...
  • Alex123980
  • Alex123980
  • 2016年06月08日 21:46
  • 1174
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:哈夫曼树的实现
举报原因:
原因补充:

(最多只允许输入30个字)