霍夫曼树,霍夫曼编码 HuffmanTree HuffmanCode c++

 计算机小白,欢迎大家一起讨论

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdlib.h>
#include<string>

//霍夫曼树结构体
struct HT
{
	int weight;//权重
	int lchild, rchild, parent;
};

//在1~i-1中找最小的两个值(s1为最小,s2为第二小,若相等则数组h中左侧的为s1
void Find(HT* h, int n, int& s1, int& s2)
{
	int i = 2;
	for (; i <= n; i++)
	{
		while (h[s1].parent)//此语句使当次s1被选中后不再被选中
			s1++;
		if (!h[i].parent)
			s1 = h[s1].weight <= h[i].weight ? s1 : i;
	}
	for (i = 2; i <= n; i++)
	{
		while (h[s2].parent||s2==s1)//此时s1被选中后还未其父节点赋值,故需排除s1
			s2++;
		if (!h[i].parent&&i!=s1)
			s2 = h[s2].weight <= h[i].weight ? s2 : i;
	}
}
void CreateHuffmanTree(HT*& h, int* w,int n)
{
	int m = 2 * n - 1;//总结点数
	int s1=1, s2=1;
	int i = 1;
	for (; i <= n; i++,w++)
		h[i] = { *w, 0, 0, 0 };
	for (; i <= m; i++)
		h[i] = { 0, 0, 0, 0 };
	for(i=n+1;i<=m;i++)
	{
		Find(h, i-1, s1, s2);
		h[s1].parent = i;
		h[s2].parent = i;
		h[i].lchild = s1;
		h[i].rchild = s2;
		h[i].weight = h[s1].weight + h[s2].weight;
	}
}

//从根节点遍历霍夫曼树,求各个节点编码
//此处我定向左走为1,向右走为0
void TraverseHuffmanTree(HT*& h, int n, char**& hc)
{
	int p = 2 * n - 1;
	int length = 0;//当前所求编码长度
	char* cd = (char*)malloc(n * sizeof(char));//临时存放编码
    //对权重重新赋值,作为标志位使用。
	//0代表初次到该节点,应向左走(如果不是叶子节点)
	//1代表已经走过左侧了,现在是从左返上来,要去右侧
	//2代表从右侧返回,直接退回(因为此节点下放已经遍历完了)
	for (int i = 1; i <= p; i++)
		h[i].weight = 0;
	while (p)
	{
		if (h[p].weight == 0)
		{
			h[p].weight = 1;//让他一会向右走
			if (h[p].lchild)
			{
				p = h[p].lchild;
				cd[length++] = '1';
			}
			else
			{
				cd[length] = '\0';
				h[p].weight = 2;//遍历到叶子节点,一会直接返回
				hc[p] = (char*)malloc(length * sizeof(char));
				strcpy(hc[p], cd);
			}
		}
		else if (h[p].weight == 1)
		{ //霍夫曼树是不存在度为1的节点的二叉树,所以如果从左侧返上来,则一定能向右侧走一个
			h[p].weight = 2;
			p = h[p].rchild;
			cd[length++] = '0';
		}
		else
		{
			p = h[p].parent;
			--length;
		}
	}
	free(cd);
}
void Print(char** hc, int n)
{
	for (int i = 1; i <= n; i++)
		printf("%s\n", hc[i]);
}
int main()
{
	int w[] = { 5,29,7,8,14,23,3,11 };
	int n = 8;
	HT* h = (HT*)malloc(2*n * sizeof(HT));//存放霍夫曼树节点的数组
	CreateHuffmanTree(h, w,n);
	char** hc = (char**)malloc(n* sizeof(char*));//指向存放编码字符串首地址的字符指针数组
	TraverseHuffmanTree(h,n,hc);
	Print(hc, n);
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值