huffmanTree的构建 编码 解码 (C++实现)

#include "stdafx.h"
#include<iostream>
#include<vector>
#include<queue>
using namespace std;

typedef struct HTNode* PtrToHTNode;
typedef char** HuffmanCodes;
typedef char* HuffmanCode;

struct HTNode
{
	int weight;
	PtrToHTNode lchild, rchild, parent;
};
struct HuffmanTree
{
	PtrToHTNode root=NULL;
	vector<PtrToHTNode>nodes;
};

void initHTNode(PtrToHTNode &h, int x);
void initHuffmanTree(HuffmanTree &hftree, int n);
void selectMin(HuffmanTree &hftree, int i, int &s1, int &s2);
void createHuffmanTree(HuffmanTree& hftree, HuffmanCodes& codes, int& n);
void levelOrderTraversal(HuffmanTree hftree);
void _levelOrderTraversal(PtrToHTNode p);
void reverseCharArray(char* c, int n);
HuffmanCode getHuffmanCode(HuffmanTree hftree, int i, int n);
HuffmanCodes getHuffmanCodes(HuffmanTree hftree, int num_of_leaves);
int decode(HuffmanTree hftree, HuffmanCode hcode);

int  main()
{
	HuffmanTree h;
	HuffmanCodes codes;
	int n;//叶子个数
	createHuffmanTree(h,codes,n);
	printf("层序遍历此哈夫曼树:");
	levelOrderTraversal(h);
	printf("\n");
	for (int i = 0; i < n; i++)
	{
		printf("%d : %s\n",h.nodes[i]->weight,codes[i]);
	}
	printf("输入编码:");
	HuffmanCode code=new char[n+1];
	scanf("%s", code);
	printf("编码 %s 对应的元素为: %d \n", code, decode(h,code));
	return 0;
}

void initHTNode(PtrToHTNode &h,int x)
{
	h = new HTNode();
	h->weight = x;
	h->parent = h->lchild = h->rchild = NULL;
}
void initHuffmanTree(HuffmanTree &hftree, int n)
{
	PtrToHTNode h=NULL;
	int tmp_weight;
	for (int i = 0; i < n; i++)
	{
		printf("第%d个结点的权值:", i + 1);
		scanf("%d", &tmp_weight);
		initHTNode(h, tmp_weight);
		hftree.nodes.push_back(h);
	}
}
void selectMin(HuffmanTree &hftree,int i,int &s1, int &s2)
{
	//在hftree.nodes[0...i]中选择权值最小两个结点, s1是最小权值结点序号,s2是次小权值结点序号
	int index = 0;
	while (hftree.nodes[index]->parent) index++;//找到vector中第一个根结点
	s1 = index;
	for (int j = 0; j < i; j++)
	{
		PtrToHTNode current_node = hftree.nodes[j];
		int current_weight = current_node->weight;
		if (!current_node->parent&&current_weight <= hftree.nodes[s1]->weight)s1 = j;
	}
	index = 0;
	while (hftree.nodes[index]->parent || index == s1)index++;
	s2 = index;
	for (int j = 0; j < i; j++)
	{
		PtrToHTNode current_node = hftree.nodes[j];
		int current_weight = current_node->weight;
		if (!current_node->parent&&current_weight <= hftree.nodes[s2]->weight&&j!=s1)s2 = j;
	}
}
void createHuffmanTree(HuffmanTree &hftree,HuffmanCodes& codes,int& n)
{
	int s1,s2;
	scanf("%d", &n);
	initHuffmanTree(hftree,n);
	PtrToHTNode h=NULL;
	for (int i = n; i < 2*n - 1; i++)
	{
		selectMin(hftree, i, s1, s2);
		initHTNode(h,hftree.nodes[s1]->weight+hftree.nodes[s2]->weight);
		h->lchild = hftree.nodes[s1];
		h->rchild = hftree.nodes[s2];
		hftree.nodes[s1]->parent = hftree.nodes[s2]->parent = h;
		hftree.nodes.push_back(h);
	}
	hftree.root = hftree.nodes[2*n - 2];
	codes = getHuffmanCodes(hftree, n);
}
void levelOrderTraversal(HuffmanTree hftree)
{
	_levelOrderTraversal(hftree.root);
}
void _levelOrderTraversal(PtrToHTNode p)
{
	queue<PtrToHTNode>myqueue;
	if (!p)return;
	myqueue.push(p);
	printf("%d ", p->weight);
	while (!myqueue.empty())
	{
		PtrToHTNode p = myqueue.front();
		myqueue.pop();
		if (p->lchild)
		{
			myqueue.push(p->lchild);
			printf("%d ", p->lchild->weight);
		}
		if (p->rchild)
		{
			myqueue.push(p->rchild);
			printf("%d ", p->rchild->weight);
		}
	}
}
HuffmanCode getHuffmanCode(HuffmanTree hftree, int i,int n)
{
	//返回第i片叶子的哈夫曼编码(字符数组形式)
	PtrToHTNode p = hftree.nodes[i];
	int max_height = n - 1,count=0;
	char* res=new char[max_height];
	while (p->parent)
	{
		PtrToHTNode parent = p->parent;
		if (parent->lchild == p)res[count++] = '0';
		else res[count++] = '1';
		p = parent;
	}
	reverseCharArray(res, count);
	res[count] = '\0';
	return res;
}
HuffmanCodes getHuffmanCodes(HuffmanTree hftree, int num_of_leaves)
{
	HuffmanCodes res = new HuffmanCode[num_of_leaves];
	for (int j = 0; j < num_of_leaves; j++)
	{
		HuffmanCode code = getHuffmanCode(hftree, j, num_of_leaves);
		res[j] = code;
	}
	return res;
}
void reverseCharArray(char* c, int n)
{
	int mid = n / 2;
	for (int i = 0; i < mid; i++)
	{
		char tmp = c[i];
		c[i] = c[n - 1 - i];
		c[n - 1 - i] = tmp;
	}
}
int decode(HuffmanTree hftree, HuffmanCode hcode)
{
	//n为编码长度
	PtrToHTNode p1 = hftree.root;
	for (int i = 0;hcode[i]!='\0'; i++)
	{
		if (hcode[i] == '0')p1 = p1->lchild;
		else p1 = p1->rchild;
	}
	return p1->weight;
}

运行效果:
在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值