二叉树应用之哈夫曼编码(二叉链表实现)

哈夫曼树的定义:(直接百度贴过来)给定n个权值作为n个叶子结点,构造一棵二叉树,若带权路径长度达到最小,
称这样的二叉树为最优二叉树,也称为哈夫曼树(Huffman tree)。哈夫曼树是带权路径长度最短的树,
权值较大的结点离根较近。具体实现定义一个结构体

typedef struct Node
{
	char data;
	int count;
	struct Node *pNext;
	struct Node *Lchild;
	struct Node *Rchild;
}Node,*pNode;
其中data保存数据,count保存数据的权值。pNext指向下一个结点。Lchild指向左子树,Rchild指向右子树。

具体实现,首先输入数据判断输入的元素在表中是否存在,如果存在则相应的权值+1,若不存在,添加新的

结点在链表末尾。然后对链表排序使其升序排列。

RT:

二叉树应用之哈夫曼编码(二叉链表实现)_第1张图片

排序完成后找到最小的两个结点,再创建新的结点使它的左右指针分别指向上述结点。再将新结点链入

表中。使之成为新的头结点。然后重复上诉工作。显然有创建的新结点->pNext==NULL时循环结束。

所得的即为哈夫曼树。

RT:

二叉树应用之哈夫曼编码(二叉链表实现)_第2张图片

最后再对生成的哈夫曼树进行编码。规定从父节点到左子树的距离定义为'0',到右子树的距离定义为'1'

RT:

二叉树应用之哈夫曼编码(二叉链表实现)_第3张图片

具体实现代码如下:

#define _CRT_SECURE_NO_WARNINGS
#include
#include
#include
#define MaxSize 100
#define Char '0'
char HuffCode[MaxSize];	// 保存哈夫曼编码
int index = 0;		// 从父节点到左子树的距离定义为'0',到右子树的距离定义为'1'
typedef struct Node
{
	char data;
	int count;
	struct Node *pNext;
	struct Node *Lchild;
	struct Node *Rchild;
}Node,*pNode;
// 创建结点用链表串起来
pNode AddNode(char ch)
{
	pNode NewNode = (pNode)malloc(sizeof(Node));
	NewNode->count = 1;
	NewNode->data = ch;
	NewNode->pNext = NewNode->Lchild =NewNode->Rchild = NULL;
	return NewNode;
}
// 创建哈夫曼树的结点
pNode AddHoffmanTree()
{
	pNode NewNode = (pNode)malloc(sizeof(Node));
	NewNode->count = 0;
	NewNode->data = Char;
	NewNode->Lchild = NewNode->Rchild = NewNode->pNext = NULL;
	return NewNode;
}
// 向链表中添加字符,若出现权值+1,若没出现再创建一个结点,连到链表后面
void IsApperaed(pNode *phead, char ch)
{
	if (*phead == NULL)
	{
		*phead = AddNode(ch);
	}
	else
	{
		pNode p = *phead;
		pNode partner = NULL;
		int flag=1;
		while (p != NULL)
		{
			partner = p;
			if (p->data == ch)
			{
				flag = 0;
				p->count++;
			}
			p = p->pNext;
		}
		if (flag)
		{
			partner->pNext = AddNode(ch);
		}
	}
}
// 打印出链表中的所有结点,及其权值
void PrintAllNode(pNode phead)
{
	pNode p = phead;
	while (p != NULL)
	{
		printf("%c的权值为:%d\n", p->data, p->count);
		p = p->pNext;
	}
}
// 对链表进行排序
void SortList(pNode phead)
{
	for (pNode p = phead; p != NULL; p = p->pNext)
	{
		for (pNode p1 = phead; p1 != NULL; p1 = p1->pNext)
		{
			if (p->count < p1->count)
			{
				Node temp;				
				temp.count = p->count;
				p->count = p1->count;
				p1->count = temp.count;			
				temp.data = p->data;
				p->data = p1->data;
				p1->data = temp.data;
			}
		}
	}
}
// 将两个结点变成新树的左右子树
void CombineNode(pNode p, pNode p1, pNode p2)
{
	p->count = p1->count + p2->count;
	p->Lchild = p1;
	p->Rchild = p2;
	p->pNext = p2->pNext;
	p1->pNext = p2->pNext = NULL;
}
// 创建哈夫曼树
pNode CreateHoffmanTree(pNode phead)
{
	SortList(phead);
	pNode pFirst = phead;
	pNode pNewHead = NULL;
	while(pFirst ->pNext!=NULL)
	{
		pNode p1 = pFirst;
		pNode p2 = p1->pNext;;
		pNewHead = AddHoffmanTree();
		CombineNode(pNewHead, p1, p2);
		pFirst = pNewHead;
	}
	return pFirst;
}
//打印哈夫曼编码 左'0' 右'1'
void BulidHoffmanCode(pNode phead)
{
	if (phead)
	{
		if (phead->Lchild)
		{
			HuffCode[index++] = '0' ;
			BulidHoffmanCode(phead->Lchild);
		}
		if (phead->Rchild)
		{
			HuffCode[index++] = '1' ;
			BulidHoffmanCode(phead->Rchild);
		}
		// 打印编码,将生产的新结点排除掉
		if (!phead->Lchild && !phead->Rchild && phead->data!=Char)
		{
			printf("%c的编码为:", phead->data);
			for (int i = 0; i

运行结果:

二叉树应用之哈夫曼编码(二叉链表实现)_第4张图片

写的很烂,只能凑合着看了。

你可能感兴趣的:(数据结构学习)