数据结构与算法—第五次作业:哈夫曼编码

/*第五次作业:
   假设在某段传输的报文中包涵12种字符,这十二种字符出现的频率分别为
           0.1,0.02,0.07,0.06,0.12,0.23,0.09,0.4,0.21,0.13,0.21,0.32  .
  请先构造哈夫曼树,然后实现该12个字符的哈夫曼编码。
  将频数转换为整数(即,叶子结点的权值):10, 2, 7, 6, 12, 23, 9, 40, 21, 13, 21, 32  .
*/

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <string>
using namespace std;

#define max 100

//define node of huffman node
struct HTNode
{
	int m_parent;
	int m_lchild;
	int m_rchild;
	int m_weight;
};
//define huffman tree
struct HTree//顺序表来定义
{
	HTNode* m_Htree;
	int m_length;
};

//init function
void initHTree(HTree& HT, int num)//num为叶子节点个数
{
	int totalNode = 2 * num - 1;//totalNode为总节点个数
	HT.m_Htree = new HTNode[totalNode];
	if (!HT.m_Htree)
	{
		cout << "init fail" << endl;
	}
	HT.m_length = 0;
	int i;
	for (i = 0; i < num; i++)//遍历初始化
	{
		HT.m_Htree[i].m_parent = -1;
		HT.m_Htree[i].m_lchild = -1;
		HT.m_Htree[i].m_rchild = -1;
		cout << "pls input the weight of " << i << endl;
		int weight;
		cin >> weight;
		HT.m_Htree[i].m_weight = weight;
		HT.m_length++;
	}
	for (; i < totalNode; i++)
	{
		HT.m_Htree[i].m_parent = -1;
		HT.m_Htree[i].m_lchild = -1;
		HT.m_Htree[i].m_rchild = -1;
		HT.m_Htree[i].m_weight = 9999;//权值初始化,先给个大值
		HT.m_length++;
	}
	cout << "init success" << endl;
}

//find two min node function
void findTwoMinNodeOfTree(HTree& HT, int pos, int& min1, int& min2)
{
	int i = 0;
	int m1, m2;//接受最小权值的位置
	int minweight;//当前根结点的最小权值
	//find min1
	while (HT.m_Htree[i].m_parent != -1)
	{
		i++;
	}
	minweight = HT.m_Htree[i].m_weight;//将找到的第一个根结点赋给minweight
	m1 = i;
	for (; i < pos; i++)
	{
		if (HT.m_Htree[i].m_weight < minweight && HT.m_Htree[i].m_parent == -1)
		{
			minweight = HT.m_Htree[i].m_weight;
			m1 = i;
		}
	}
	HT.m_Htree[m1].m_parent = 1;//change the node state to not root
	min1 = m1;

	//find min2
	i = 0;
	while (HT.m_Htree[i].m_parent != -1)
	{
		i++;
	}
	minweight = HT.m_Htree[i].m_weight;
	m2 = i;
	for (; i < pos; i++)
	{
		if (HT.m_Htree[i].m_weight < minweight && HT.m_Htree[i].m_parent == -1)
		{
			minweight = HT.m_Htree[i].m_weight;
			m2 = i;
		}
	}
	HT.m_Htree[m2].m_parent = 1;//change the node state to not root
	min2 = m2;
}

//function of createHtree
void createHuffmanTree(HTree& HT, int num)
{
	if (!HT.m_Htree)
	{
		cout << "the tree is not exist" << endl;
	}
	int i, min1, min2;
	for (i = num; i < HT.m_length; i++)
	{
		findTwoMinNodeOfTree(HT, i, min1, min2);
		HT.m_Htree[min1].m_parent = i;
		HT.m_Htree[min2].m_parent = i;
		HT.m_Htree[i].m_lchild = min1;
		HT.m_Htree[i].m_rchild = min2;
		HT.m_Htree[i].m_weight = HT.m_Htree[min1].m_weight + HT.m_Htree[min2].m_weight;
	}
}

//function of huffman coding        哈夫曼树编码
void HuffmanCoding(HTree& HT, char**& HC)
{
	int numOfCode = (HT.m_length + 1) / 2;
	HC = new char* [numOfCode];//array of char array,每一个编码都是一个字符数组
	if (!HC)
	{
		cout << "huffmancode mem fail" << endl;
	}
	char* code = new char[numOfCode];//字符数组不能直接赋值,只能拷贝
	if (!code)//判断空间是否给我们
	{
		cout << "code mem fail" << endl;
	}
	int cur = HT.m_length - 1;//pos in array
	int codelen = 0;

	//visit state :  0:not visit  ;  1:lchild visited  ;  2:all visited
	int i;
	for (i = 0; i < HT.m_length; i++)
	{
		HT.m_Htree[i].m_weight = 0;  //初始化所有的结点权值为0
	}
	while (cur != -1)  //判断该节点的左右儿子是否为-1,即叶节点,此时该编码结束
	{
		if (HT.m_Htree[cur].m_weight == 0)//从头节点开始遍历
		{
			HT.m_Htree[cur].m_weight = 1;//表示访问过,变flag
			if (HT.m_Htree[cur].m_lchild != -1)//判断是不是叶节点
			{
				code[codelen++] = '0';
				cur = HT.m_Htree[cur].m_lchild;//让它沿着左儿子方向走
			}
			else
			{//已经为叶结点时
				code[codelen] = '\0';//终止符
				HC[cur] = new char[codelen + 1];//申请一个空间
				if (!HC[cur])//判断地址给没给我们
				{
					cout << "code mem fail" << endl;
				}
				strcpy(HC[cur], code);//拷贝
			}
		}
		else if (HT.m_Htree[cur].m_weight == 1)//右侧
		{
			HT.m_Htree[cur].m_weight = 2;
			if (HT.m_Htree[cur].m_rchild != -1)//判断右儿子是否到叶结点
			{
				code[codelen++] = '1';
				cur = HT.m_Htree[cur].m_rchild;
			}
		}
		else//其他情况时
		{
			HT.m_Htree[cur].m_weight = 0;
			cur = HT.m_Htree[cur].m_parent;
			--codelen;
		}
	}
	delete[]code;
}

//show code
void showHuddmanCode(char**& HC, int numOfCode)
{
	for (int j = 0; j < numOfCode; j++)
	{
		cout << "the code is " << HC[j] << endl;
	}
}

//list the huffmantree
void showTree(HTree& HT)
{
	if (HT.m_Htree != NULL)
	{
		cout << "show the node of huffmantree" << endl;
		for (int i = 0; i < HT.m_length; i++)
		{
			cout << HT.m_Htree[i].m_parent <<"    "
				 << HT.m_Htree[i].m_lchild <<"    "
				 << HT.m_Htree[i].m_rchild <<"    "
				<< HT.m_Htree[i].m_weight << endl;
		}
	}
}

//test
void test()
{
	cout << "pls input the num of leaf node" << endl;
	int num;
	cin >> num;
	HTree mytree;
	initHTree(mytree, num);
	int pos, min1, min2;
	pos = mytree.m_length;
	findTwoMinNodeOfTree(mytree, pos, min1, min2);
	cout << "min1=  " << min1 << endl;
	cout << "min2=  " << min2 << endl;
	showTree(mytree);
}

void test01()
{
	cout << "pls input the num of leaf node" << endl;
	int num;
	cin >> num;
	HTree mytree;
	initHTree(mytree, num);
	createHuffmanTree(mytree, num);
	showTree(mytree);
	cout << "***************************" << endl;
	char** hcode;
	HuffmanCoding(mytree, hcode);
	cout << "***************************" << endl;
	showHuddmanCode(hcode, num);
}

int main()
{
	test01();
	//test();
	system("pause");
	return 0;
}

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值