哈夫曼树的创建和哈夫曼编码

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<limits.h>
#include<string.h>
//int n1 = 0, n2 = 0;
#pragma warning(disable:4996)
struct Huffunode//定义哈夫曼树结点
{
	int weight;
	int parent;
	int lchild;
	int rchild;
};

void select(Huffunode huffutree[], int n, int& n1, int& n2)//定义返回数组两个最小值下标,由于用return只能返回一个值故可以使用引用或者全局变量或者结构体
{
	int a[1000];//将哈夫曼树中叶节点的权值拷贝到数组a中下标一致
	for (int i = 0; i < n; i++)
	{
		a[i] = huffutree[i].weight;
	}
	//for(int i=0;i<n;i++)
	//printf("%d  ", a[i]);
	//printf("\n");
	int s1 = INT_MAX,s2 = INT_MAX;//初始化两个储存变量为最大值,头文件为limits.h
	//printf("%d\n", n);
	for (int i = 0; i < n; i++)//选择比较过程,若该数组元素a[i]比s1和s2都小且该结点没有父亲结点parent域为-1则将s2的值改为s1,s1的值改为a[i],n2改为n1,n1改为i
	{
		if (a[i] < s1 && a[i] < s2&&huffutree[i].parent == -1)
		{
			s2 = s1;
			s1 = a[i];
			n2 = n1;//n1,n2为引用变量,形参变实参变
			n1 = i;
			//printf("%d,%d\n", n1, n2);
		}
		else if (a[i] > s1&&a[i] < s2&&huffutree[i].parent == -1)//若a[i]比s1大但是比s2小且该结点没有父亲结点parent域为-1则将s2的值改为a[i],n2的值改为i
		{
			s2 = a[i];
			n2 = i;
			//printf("%d,%d\n", n1, n2);
		}

	}
}

void createhuffmantree(Huffunode  huffutree[], int w[], int n)//创建哈夫曼树
{
	for (int i = 0; i < 2 * n - 1; i++)//初始化,若叶子数为n则哈夫曼树结点数为2n-1.
	{
		huffutree[i].parent = -1;
		huffutree[i].lchild = -1;
		huffutree[i].rchild = -1;
	}
	for (int i = 0; i < n; i++)//给叶子结点赋权值
		huffutree[i].weight = w[i];

	for (int i = n; i < (2 * n) - 1; i++)//构建过程
	{
		int n1 = 0, n2 = 0;
		select(huffutree, i, n1, n2);//选择已有哈夫曼树结点中两个权值最小且没有双亲的结点
		//printf("%d %d\n", n1, n2);
		huffutree[i].weight = huffutree[n1].weight + huffutree[n2].weight;//连接
		huffutree[n1].parent = i;
		huffutree[n2].parent = i;
		huffutree[i].lchild = n1;
		huffutree[i].rchild = n2;
		//printf("%d %d  %d  %d\n", huffutree[i].weight, huffutree[i].parent, huffutree[i].lchild, huffutree[i].rchild);
	}

}

void huffucoding(Huffunode huffutree[], char* huffunode[],  int n)//哈夫曼树编码
{
	char *temp=(char*)malloc(sizeof(char)*n);//开辟一个长度为n的数组temp
	temp[n-1] = '\0';//将最后一个位置储存’\0'结束符,方面用%s输出
	for (int i = 0; i < n; i++)
	{
		int t = 0;
		int cur = n-1;//储存哈夫曼码位置
		int pos = i;//当前处理结点
		int parent = huffutree[i].parent;//当前结点的双亲结点
		while (parent != -1)//如果当前结点有双亲则进入循环,从叶子到根逆向编码
		{
			if (huffutree[parent].lchild ==pos)//当前结点是双亲结点的左孩子编码为0,否则编码为1
			{
				temp[--cur] =' 0';
				t++;
			}
			else if (huffutree[parent].rchild == pos)
			{
				temp[--cur] ='1';
				t++;
			}
			pos = parent;//指向下一个结点
			parent = huffutree[parent].parent;
		}
		/*for(int i=0;i<t;i++)
		printf("  %d", temp[cur+i]);
		printf("\n");*/
		//printf("%s\n", &temp[cur]);
		huffunode[i] = (char*)malloc(sizeof(char)*(n - cur));//开辟哈夫曼编码长度的数组,并用指针数组的i个元素指向首地址
		strncpy(huffunode[i], &temp[cur],n-cur);//将临时开辟temp指向的空间的值拷贝到huffunode[i]指向的区域
	}
	free(temp);//释放临时开辟的空间
}

int main()//测试
{
Huffunode huffutree[1000];
char* huffunode[1000];
int w []={11,4,6,2,13,25,8,16 };
createhuffmantree(huffutree, w, 8);
printf("哈夫曼树如下:\n");
printf("       权值   父亲结点序号   左孩子序号    右孩子序号\n");
for (int i = 0; i < 15; i++)
{
	printf("下标%2d: %3d %9d  %12d  %12d\n",i, huffutree[i].weight, huffutree[i].parent, huffutree[i].lchild, huffutree[i].rchild);
}
huffucoding(huffutree,huffunode, 8);
for (int i = 0; i < 8; i++)
{
	printf(" %d:%s\n",huffutree[i].weight, huffunode[i]);
}
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值