哈夫曼树的定义:(直接百度贴过来)给定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:
排序完成后找到最小的两个结点,再创建新的结点使它的左右指针分别指向上述结点。再将新结点链入
表中。使之成为新的头结点。然后重复上诉工作。显然有创建的新结点->pNext==NULL时循环结束。
所得的即为哈夫曼树。
RT:
最后再对生成的哈夫曼树进行编码。规定从父节点到左子树的距离定义为'0',到右子树的距离定义为'1'
RT:
具体实现代码如下:
#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
运行结果:
写的很烂,只能凑合着看了。