构建哈夫曼树和编码输出

c++代码实现:

// MyTest.cpp : 定义控制台应用程序的入口点。
/*哈夫曼构建
思想是弄成一个结构体数组,结构体数据本身就具备了表的特征
*/

#include "stdafx.h"
#include <algorithm>
#include <cstring>
#include <cstdlib>
#include <iostream>
using namespace std;
#define MAXBIT	100
#define MAXVALUE 10000
#define MAXLEAL 6
#define MAXNODE MAXLEAL*2-1
typedef struct{
	double weight;//权值
	int parent;//父节点
	int lchild;//左孩子 
	int rchild;//右孩子
	char value;//该节点表示的字符
}HNodeType;
typedef struct{
	int bit[MAXBIT];//存储编码的数组
	int start;//编码开始下标
}HCodeType;//编码结构体
HNodeType HuffNode[MAXNODE];//定义一个结构体节点数组
HCodeType HuffCode[MAXLEAL];//定义一个编码结体体数组
/*构建啥夫曼编码*/
void HuffManTree(HNodeType HuffNode[MAXNODE], int n){
	/*i,j两个循环变量;x1,x2两个最小权值结点在数组中的序号*/
	int  x1, x2;
	double m1, m2;
	/*初始化哈夫曼树数组huffmanNode[]中的结点*/
	for (int i = 0; i < 2 * n - 1; i++){
		HuffNode[i].weight = 0;
		HuffNode[i].parent = -1;
		HuffNode[i].lchild = -1;
		HuffNode[i].rchild = -1;
	}
	/*输入n个叶子结点的权值*/
	for (int i = 0; i < n; i++){
		cout << "please input the weight and value of huffman" << i + 1 << endl;
		cin >> HuffNode[i].weight >> HuffNode[i].value;
	}
	//构造huffman树
	for (int i = 0; i < n - 1; i++){
		//执行n-1次合并
		m1 = m2 = MAXVALUE;
		/*m1,m2存放两个无父节点,且节点值最小的两个数*/
		x1 = x2 = 0;
		for (int j = 0; j < n + i; j++){
			if (HuffNode[j].weight < m1&&HuffNode[j].parent == -1){
				//比第一个数权值小的时候
				m2 = m1;//m2存次小的数权值
				x2 = x1;
				m1 = HuffNode[j].weight;
				x1 = j;
			}
			else if (HuffNode[j].weight < m2&&HuffNode[j].parent == -1){
				m2 = HuffNode[j].weight;
				x2 = j;
			}
		}
		//更新找到的子结点x1,x2的父结点信息量
		HuffNode[x1].parent = n + i;
		HuffNode[x2].parent = n + i;
		HuffNode[n + i].weight = m1 + m2;
		HuffNode[n + i].lchild = x1;
		HuffNode[n + i].rchild = x2;
		cout << "the x1.weight and x2.weight in round" << i + 1 << "\t" << HuffNode[x1].weight <<"\t"<< HuffNode[x2].weight << endl;
	}
}
/*哈夫曼编码*/
void HuffmanCode(HCodeType HuffCode[MAXLEAL], int n){
	HCodeType cd;//定义一个变量用来求解解码时的信息
	int c, p;
	for (int i = 0; i < n; i++){
		cd.start = n - 1;
		c = i;//因为在构建哈夫曼树时,是从最小两个权值找起的,所以i=0一定是叶子结点
		p = HuffNode[c].parent;
		while (p != -1){
			if (HuffNode[p].lchild == c)cd.bit[cd.start] = 0;
			else cd.bit[cd.start] = 1;
			cd.start--;//求编码的低一位
			c = p;//往上移,看父节点的左孩子是不是与C(代表此时的节点)相等
			p = HuffNode[c].parent;//设置下一个循环条件
		}
		/*把叶子结点的编码信息从临时的cd中复制出来,放入数据结构体来*/
		for (int j = cd.start + 1; j < n; j++)
			HuffCode[i].bit[j] = cd.bit[j];
		HuffCode[i].start = cd.start;//每次编码记录下cd.start的值
	}
}
int _tmain(int argc, _TCHAR* argv[])
{
	int n;
	cout << "please input n:" << endl;
	cin >> n;
	HuffManTree(HuffNode, n);/*构造哈夫曼树*/
	HuffmanCode(HuffCode, n);/*哈夫曼编码*/
	/*输出已经保存好的所有哈夫曼编码*/
	for (int i = 0; i < n; i++){
		cout << HuffNode[i].value << ":Haffman code is: ";
		for (int j = HuffCode[i].start + 1; j < n; j++)
			cout << HuffCode[i].bit[j];
		cout << endl;
	}
	return 0;
}


C代码实现:

// MyTest.cpp : 定义控制台应用程序的入口点。
/*哈夫曼构建
思想是弄成一个结构体数组,结构体数据本身就具备了表的特征
*/

#include "stdafx.h"
#include <stdio.h>
#pragma warning(disable:4996)
#define MAXNODE 100
#define MAXTREEHIGH 30

#define MAXVALUE 1000//先定义一个最大值,以找出哈夫曼树组的两个最小值
typedef struct{
	double weight;//权值
	int parent;
	int lchild;
	int rchild;
	char value;
}HNodeType;//节点信息抽象
typedef struct{
	int bit[MAXNODE];
	int start;
}HCodeType;//编码,每个节点对应一个编码
HNodeType HuffNode[MAXNODE];/*定义结点数组,形成一个结点信息表*/
HCodeType HuffCode[MAXTREEHIGH];/*定义哈夫曼树高,以编码*/

/*构建哈夫曼树*/
void BiludeHaffmanTree(HNodeType HuffNode[MAXNODE], int n){
	int x1, x2;//两个最小权值的数组的序号
	double m1, m2;//两个最小权值的值
	/*找出所有结点中权值最小、无父结点的两个结点,并合并为一棵二叉树*/
	for (int i = 0; i < 2 * n - 1; i++){//n个叶子节点的二叉树,则有2n-1的结点
		HuffNode[i].weight = 0;
		HuffNode[i].parent = -1;
		HuffNode[i].lchild = -1;
		HuffNode[i].rchild = -1;
	}
	/*输入叶子结点的权值*/
	for (int i = 0; i < n; i++){
		printf("Please input value and weight of lead node:%d\n", i + 1);
		scanf(" %c%lf", &HuffNode[i].value, &HuffNode[i].weight);//这里double类型的输入,这里出错,调了很长时间

		//scanf(" %lf", &HuffNode[i].weight);
		//scanf("%f%c", &HuffNode[i].weight, &HuffNode[i].value );
	}

	//开始构建
	for (int i = 0; i < n - 1; i++){
		m1 = m2 = MAXVALUE;
		x1 = x2 = 0;
		for (int j = 0; j < n + i; j++){//从哈夫曼数组中找,n+i为存储两个最小权值加值
			//不用担心同样值的构造出来的权值与原数组中值相同,因为构造出来权值在后面
			if (HuffNode[j].weight < m1&&HuffNode[j].parent == -1){
				m2 = m1;
				x2 = x1;
				m1 = HuffNode[j].weight;
				x1 = j;
			}
			else if (HuffNode[j].weight < m2&&HuffNode[j].parent == -1){
				m2 = HuffNode[j].weight;
				x2 = j;
			}
		}
		//设置x1,x2父结点
		HuffNode[x1].parent = n + i;
		HuffNode[x2].parent = n + i;
		HuffNode[n + i].weight = m1 + m2;
		HuffNode[n + i].lchild = x1;
		HuffNode[n + i].rchild = x2;
		printf("x1.weight and x2.weight in round %d:\t%.3f\t%.3f\n", i + 1,HuffNode[x1].weight,HuffNode[x2].weight);
	}
}

/*哈夫曼编码*/
void BiludHaffmanCode(HCodeType HuffCode[MAXTREEHIGH], int n){
	HCodeType cd;/*定义一个编码的临时变量*/
	int c, p;//p代表父节点
	for (int i = 0; i < n; i++){
		cd.start = n - 1;
		c = i;
		p = HuffNode[c].parent;
		while (p != -1){
			if (HuffNode[p].lchild == c)
				cd.bit[cd.start] = 0;
			else
				cd.bit[cd.start] = 1;
			cd.start--;
			c = p;
			p = HuffNode[c].parent;
		}
		/*把叶子结点编码信息从临时编码cd中复制出来,放入编码结构体数组中*/
		for (int j = cd.start + 1; j < n; j++)
			HuffCode[i].bit[j] = cd.bit[j];
		HuffCode[i].start = cd.start;
	}
}

int _tmain(int argc, _TCHAR* argv[])
{
	int n;
	printf("Please input the n: ");
	scanf("%d", &n);
	BiludeHaffmanTree(HuffNode, n);
	BiludHaffmanCode(HuffCode, n);

	for (int i = 0; i < n; i++){
		printf("%c  :Huffmancode is :", HuffNode[i].value);
		for (int j = HuffCode[i].start + 1; j < n; j++)
			printf("%d", HuffCode[i].bit[j]);
		printf("\n");
	}
	return 0;
}


猜你喜欢

转载自blog.csdn.net/guangod/article/details/82655335