哈夫曼解码

解码步骤:

1、读取按顺序读取文件中的字符使用次数、原文件字符长度、哈夫曼编码长度、哈夫曼编码

2、和编码步骤一样,通过字符使用次数构建哈夫曼树

3、根据哈夫曼树,对哈夫曼编码进行解码,把其解码出来的内容写入原文件字符大小的动态数组中

4、把数组写入新文件

代码实现

struct HufNode
{
	unsigned char c;
	char code;
	int usetime;
	//
	HufNode *pParent;
	HufNode *pLc;
	HufNode *pRc;
};

//拷贝数组
struct HufArrayNode
{
	int usetimes;
	HufNode *pRoot;
};

//进行数组和树之间的转接
struct HufData
{
	unsigned char c;
	int usetime;
	HufNode *pRoot;
};

bool FindMinHufDataInHufArray(HufArrayNode *pHufArray, HufData &hufdata)
{
	hufdata.c = '\0';
	hufdata.usetime = 0;

	for (int i = 0; i < 256; ++i)
	{
		if (hufdata.usetime == 0)
		{
			if (pHufArray[i].usetimes> 0)
			{
				hufdata.c = i;
				hufdata.usetime = pHufArray[i].usetimes;
				hufdata.pRoot = pHufArray[i].pRoot;
			}
		}
		else
		{
			if (pHufArray[i].usetimes > 0)
			{
				if (pHufArray[i].usetimes < hufdata.usetime)
				{
					hufdata.c = i;
					hufdata.usetime = pHufArray[i].usetimes;
					hufdata.pRoot = pHufArray[i].pRoot;
				}
			}
		}
	}

	if (hufdata.usetime > 0)
	{
		pHufArray[hufdata.c].usetimes = 0;
		pHufArray[hufdata.c].pRoot = nullptr;
		return true;
	}
	else
	{
		return false;
	}
}
bool FindMinOver(HufArrayNode const * const pHufArray)
{
	int num = 0;
	for (int i = 0; i < 256; ++i)
	{
		if (pHufArray[i].usetimes>0)
		{
			++num;
		}
	}
	return num == 1;
}
void DestroyTree(HufNode *pRoot)
{
	if (pRoot->pLc)
	{
		DestroyTree(pRoot->pLc);
	}
	if (pRoot->pRc)
	{
		DestroyTree(pRoot->pRc);
	}

	if (pRoot)
	{
		delete pRoot;
		pRoot = nullptr;
	}
}

HufNode *pRoot;
int _tmain(int argc, _TCHAR* argv[])
{
	if (argc < 2)
	{
		printf("没有待解码文件\n");
		getchar();
		return 0;
	}

	FILE *fp = nullptr;
	fopen_s(&fp, argv[1], "rb");
	printf("读取文件\n");
	if (fp)
	{
		int hufcodearray[256];
		int orgfilesize;
		int hufcodesize;
		unsigned char *pHufCodeData;
		
		fread(hufcodearray, sizeof(int), 256, fp);
		fread(&orgfilesize, sizeof(int), 1, fp);
		fread(&hufcodesize, sizeof(int), 1, fp);
		pHufCodeData = new unsigned char[hufcodesize];
		fread(pHufCodeData, sizeof(unsigned char), hufcodesize, fp);

		fclose(fp);
		fp = nullptr;
		printf("读取成功\n");

		HufArrayNode hufarray[256];

		for (int i = 0; i < 256;++i)
		{
			hufarray[i].usetimes = hufcodearray[i];
			hufarray[i].pRoot = nullptr;
		}

		printf("开始建树\n");
		HufData hufdata;
		while (!FindMinOver(hufarray))
		{
			HufNode *pTempRc;
			HufNode *pTempLc;
			HufNode *pTempRoot;

			if (FindMinHufDataInHufArray(hufarray, hufdata))
			{
				if (hufdata.pRoot)
				{
					pTempRc = hufdata.pRoot;
					pTempRc->c = 0;
					pTempRc->code = 0;
				}
				else
				{
					pTempRc = new HufNode;
					pTempRc->c = hufdata.c;
					pTempRc->code = 0;
					pTempRc->usetime = hufdata.usetime;
					pTempRc->pParent = nullptr;
					pTempRc->pLc = nullptr;
					pTempRc->pRc = nullptr;
				}
			}

			if (FindMinHufDataInHufArray(hufarray, hufdata))
			{
				if (hufdata.pRoot)
				{
					pTempLc = hufdata.pRoot;
					pTempLc->c = 0;
					pTempLc->code = 1;
				}
				else
				{
					pTempLc = new HufNode;
					pTempLc->c = hufdata.c;
					pTempLc->code = 1;
					pTempLc->usetime = hufdata.usetime;
					pTempLc->pParent = nullptr;
					pTempLc->pLc = nullptr;
					pTempLc->pRc = nullptr;
				}
			}

			pTempRoot = new HufNode;
			pTempRoot->code = 0;
			pTempRoot->c = 0;
			pTempRoot->usetime = pTempRc->usetime + pTempLc->usetime;
			pTempRoot->pParent = nullptr;
			pTempRoot->pLc = pTempLc;
			pTempRoot->pRc = pTempRc;

			pTempRc->pParent = pTempRoot;
			pTempLc->pParent = pTempRoot;
			
			for (int i = 0; i < 256;++i)
			{
				if (hufarray[i].usetimes == 0)
				{
					hufarray[i].usetimes = pTempRoot->usetime;
					hufarray[i].pRoot = pTempRoot;
					break;
				}
			}
		}

		if (FindMinHufDataInHufArray(hufarray,hufdata))
		{
			pRoot = hufdata.pRoot;
			printf("建树完成\n");
		}

		HufNode *pCurrent = nullptr;
		int ByteSit = 0;
		int BitSit = 0;
		unsigned char *pOutBuffer = new unsigned char[orgfilesize];
		
		for (int o = 0; o < orgfilesize;++o)
		{
			pCurrent = pRoot;
			while (pCurrent->pRc || pCurrent->pLc)
			{
				switch (BitSit)
				{
				case 0:
				{
						  if (pHufCodeData[ByteSit] & 0x80)
						  {
							  pCurrent = pCurrent->pLc;
						  }
						  else
						  {
							  pCurrent = pCurrent->pRc;
						  }
				}
					break;
				case 1:
				{
						  if (pHufCodeData[ByteSit] & 0x40)
						  {
							  pCurrent = pCurrent->pLc;
						  }
						  else
						  {
							  pCurrent = pCurrent->pRc;
						  }
				}
					break;
				case 2:
				{
						  if (pHufCodeData[ByteSit] & 0x20)
						  {
							  pCurrent = pCurrent->pLc;
						  }
						  else
						  {
							  pCurrent = pCurrent->pRc;
						  }
				}
					break;
				case 3:
				{
						  if (pHufCodeData[ByteSit] & 0x10)
						  {
							  pCurrent = pCurrent->pLc;
						  }
						  else
						  {
							  pCurrent = pCurrent->pRc;
						  }
				}
					break;
				case 4:
				{
						  if (pHufCodeData[ByteSit] & 0x08)
						  {
							  pCurrent = pCurrent->pLc;
						  }
						  else
						  {
							  pCurrent = pCurrent->pRc;
						  }
				}
					break;
				case 5:
				{
						  if (pHufCodeData[ByteSit] & 0x04)
						  {
							  pCurrent = pCurrent->pLc;
						  }
						  else
						  {
							  pCurrent = pCurrent->pRc;
						  }
				}
					break;
				case 6:
				{
						  if (pHufCodeData[ByteSit] & 0x02)
						  {
							  pCurrent = pCurrent->pLc;
						  }
						  else
						  {
							  pCurrent = pCurrent->pRc;
						  }
				}
					break;
				case 7:
				{
						  if (pHufCodeData[ByteSit] & 0x01)
						  {
							  pCurrent = pCurrent->pLc;
						  }
						  else
						  {
							  pCurrent = pCurrent->pRc;
						  }
				}
					break;
				default:
					break;
				}

				++BitSit;

				if (BitSit >= 8)
				{
					BitSit = 0;
					++ByteSit;
				}
			}
			pOutBuffer[o] = pCurrent->c;
		}
		
		string outfilename = argv[1];
		outfilename.pop_back();
		outfilename.pop_back();
		outfilename.pop_back();
		outfilename.pop_back();
		outfilename += ".txt";
		
		FILE *outfp = nullptr;
		fopen_s(&outfp, outfilename.c_str(), "wb");
		if (outfp)
		{
			fwrite(pOutBuffer, sizeof(unsigned char), orgfilesize, outfp);
			fclose(outfp);
			outfp = nullptr;
		}
		else
		{
			printf("解码文件暂时无法写入!");
		}

		SAFE_DELARR(pOutBuffer);
		DestroyTree(pRoot);
		SAFE_DELARR(pHufCodeData);
	}
	else
	{
		printf("待解码的文件不存在或暂时无法打开!\n");
	}
	
	getchar();
	return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值