哈夫曼树及哈夫曼编码数据结构与算法

计算机数据处理中,哈夫曼编码使用变长编码表对源符号(如文件中的一个字母)进行编码,其中变长编码表是通过一种评估来源符号出现机率的方法得到的,出现机率高的字母使用较短的编码,反之出现机率低的则使用较长的编码,这便使编码之后的字符串的平均长度、期望值降低,从而达到无损压缩数据的目的。

//哈夫曼树及哈夫曼编码
#include<stdio.h>
#include<stdlib.h>
#define MAXSIZE 30

typedef struct node
{
	int data;//节点数据
	struct node* lchild, * rchild;//定义左右孩子指针
	struct node* next;//单链表节点,next为节点指针
}BSTree_Link;//二叉树单链表节点类型

BSTree_Link* CreateLinkList(int n); //根据叶子节点的权值生成一个升序单链表
void print(BSTree_Link* h);//输出单链表
BSTree_Link* HuffTree(BSTree_Link* Link);//生成哈夫曼树
void Inorder(BSTree_Link* p);//中序遍历二叉树
void Preorder(BSTree_Link* p);//先序遍历二叉树
void HuffCode(BSTree_Link* p);//后序遍历哈夫曼树并输出哈夫曼编码

void main()
{
	BSTree_Link* root;
	int n;
	printf("请输入叶子节点个数:\n");
	scanf("%d", &n);
	printf("请输入节点的权值:\n");
	root = CreateLinkList(n);
	printf("输出生成的升序单链表:\n");
	print(root);
	root = HuffTree(root);//生成哈夫曼树
	printf("先序遍历输出哈夫曼树个结点的值:\n");
	Preorder(root);
	printf("\n");
	printf("中序遍历输出哈夫曼树个结点的值:\n");
	Inorder(root);
	printf("后序遍历输出哈夫曼树个节点的值:\n");
	HuffCode(root);
}

BSTree_Link* CreateLinkList(int n) //根据叶子节点的权值生成一个升序单链表
{
	BSTree_Link* link, * p, * q, * s;
	int i;
	link = (BSTree_Link*)malloc(sizeof(BSTree_Link));//生成单链表的头节点
	s = (BSTree_Link*)malloc(sizeof(BSTree_Link));//生成单链表第一个数据节点,即哈夫曼树的叶节点
	scanf("%d", &s->data);//输入叶子节点权值
	s->lchild = NULL;
	s->rchild = NULL;
	s->next = NULL;
	link->next = s;
	for (i = 2; i <= n; i++)
	{
		s = (BSTree_Link*)malloc(sizeof(BSTree_Link));//生成一个数据节点
		scanf("%d", &s->data);
		s->lchild = NULL;
		s->rchild = NULL;
		q = link;//按照升序插入单链表
		p = q->next;
		while(p != NULL)
		
			if (s->data > p->data)//查找插入位置后进行插入
			{
				q = p;
				p = p->next;
			}
			else
			{
				q->next = s;
				s->next = p;
				break;
			}
			if (s-> data > q->data)
			{
				q->next = s;
				s->next = p;
			}
			return link;
	}
}

void print(BSTree_Link* h)//输出单链表
{
	BSTree_Link* p;
	p = h->next;
	while (p != NULL)
	{
		printf("%d,", p->data);
		p = p->next;
	}
	printf("\n");
}

BSTree_Link* HuffTree(BSTree_Link* link)//生成哈夫曼树
{
	BSTree_Link* p, * q, * s;
	while (link->next != NULL)
	{
		p = link->next;
		q = p->next;
		link->next = q->next;
		s = (BSTree_Link*)malloc(sizeof(BSTree_Link));
		s->data = p->data + q->data;
		s->lchild = p;
		s->lchild = q;
		q = link;
		p = q->next;
		while(p!=NULL)
			if (s->data > p->data)
			{
				q = p;
				p = p->next;
			}
			else
			{
				q->next = s;
				s->next = p;
				break;
			}
		if (q != link && s->data > q->data)
		{
			q->next = s;
			s->next = p;
		}
	}
	return s;
}

void Inorder(BSTree_Link* p)//中序遍历二叉树
{
	if (p != NULL)
	{
		Inorder(p->lchild);
		printf("%4d", p->data);
		Inorder(p->rchild);
	}
}

void Preorder(BSTree_Link* p)//先序遍历二叉树
{
	if (p != NULL)
	{
		printf("%4d", p->data);
		Preorder(p->lchild);
		Preorder(p->rchild);
	}
}

void HuffCode(BSTree_Link* p)//后序遍历哈夫曼树并输出哈夫曼编码
{
	BSTree_Link* q, * stack[MAXSIZE];
	int b, i = -1, j = 0, k, code[MAXSIZE];
	do
	{
		while (p != NULL)
		{
			if (p->lchild == NULL && p->rchild == NULL)
			{
				printf("叶节点信息:key=%3d,code:", p->data);
				for (k = 0; k < j; k++)
					printf("%d", code[k]);
				printf("%d", code[k]);
				printf("\n");
				j--;
			}
			stack[++i] = p;
			p = p->lchild;
			code[j++] = 0;
		}
		q = NULL;
		b = 1;
		while (i >= 0 && b)
		{
			p = stack[i];
			if (p->rchild == q)
			{
				i--; j--;
				q = p;
			}
			else
			{
				p = p->rchild;
				code[j++] = 1;
				b = 0;
			}
		}
	} while (i >= 0);
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

惑星撞地球

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值