总所周知huffman编码能有效的减小码长,其实现的
思想如下:
首先找出最小的两个数,求其和值为另一个数,插入到原数中,之后再从数中找出最小的两个,依次类推,直到最后一个数的概论为一结束。
我是用链表实现的,首先把所有的数存放到一个链表里面,从小到大的排序(用一个排序函数实现),之后去头结点和下一个节点合并为一个新的节点,查到链表的头部,两个节点分别为其左右孩子,左边的编码为0,右边的编码为1,同时将它们从链表中删除,这样有用排序函数排序一下链表,重复上面的操作直到链表只有一个节点,也即该节点的概率为1(我是用这个来判断是否结束建树的,以及遍历树的),这样就生成了一颗huffman树,之后就是遍历huffman树,打印编码,最后是销毁整棵huffman树。
源代码如下:
/*
* This code has a disadvantage that you should change the NodeNum
* when you use another probability sets
* In this code NodeNum = 3 means there are 4 nodes!
* But I will try to solve this problem!
*/
#include <stdio.h>
#include <stdlib.h>
#define LEN sizeof(struct HuffNode)
#define NodeNum 3
struct HuffNode
{
float gailv;
int code;
struct HuffNode *Next;
struct HuffNode *Parent;
struct HuffNode *Lchild;
struct HuffNode *Rchild;
};
struct HuffNode *creatLink()
{
struct HuffNode *head, *TempNode1, *TempNode2;
int flag = NodeNum;
float NodeGailv = 0.0;
printf("Please input %d gailv and the total of their proority should be 1.0!\n\n", NodeNum+1);
TempNode1 = (struct HuffNode *) malloc(LEN);
TempNode1->code = 0;
TempNode1->Parent = NULL;
TempNode1->Lchild = NULL;
TempNode1->Rchild =NULL;
TempNode1->Next =NULL;
head = TempNode1;
printf("please input the priority:\n");
scanf("%f", &TempNode1->gailv);
NodeGailv = NodeGailv + TempNode1->gailv;
TempNode1->code = 0;
TempNode2 = TempNode1;
while(flag)
{
TempNode1 = (struct HuffNode *) malloc(LEN);
TempNode2->Next = TempNode1;
printf("please input the prabobility:\n");
scanf("%f", &TempNode1->gailv);
TempNode1->code = 0;
TempNode1->Parent = NULL;
TempNode1->Lchild = NULL;
TempNode1->Rchild = NULL;
TempNode1->Next = NULL;
flag--;
TempNode2 = TempNode1;
NodeGailv = NodeGailv + TempNode1->gailv;
//printf(" gailv is %f\n", NodeGailv);
}
TempNode2->Next = NULL;
if(NodeGailv == 1.0) { return head; }
else
{
printf("Gailv is not 1.0, you input the wrong priorities!\n");
return NULL;
}
}
void printLink(struct HuffNode *head)
{
struct HuffNode *HuffHead = head;
while(HuffHead != NULL)
{
printf("The prabobility is : %7.4f and the code is :%d\n", HuffHead->gailv, HuffHead->code);
HuffHead = HuffHead->Next;
}
}
void swapNode(struct HuffNode *node1, struct HuffNode *node2)
{
struct HuffNode *temp = (struct HuffNode *)malloc(LEN);
temp->code = node1->code;
temp->gailv = node1->gailv;
temp->Parent = node1->Parent;
temp->Lchild = node1->Lchild;
temp->Rchild = node1->Rchild;
//temp->Next = node1->Next;
node1->code = node2->code;
node1->gailv = node2->gailv;
node1->Parent = node2->Parent;
node1->Lchild = node2->Lchild;
node1->Rchild = node2->Rchild;
// node1->Next = node2->Next;
node2->code = temp->code;
node2->gailv = temp->gailv;
node2->Parent = temp->Parent;
node2->Lchild = temp->Lchild;
node2->Rchild = temp->Rchild;
//node2->Next = temp->Next;
}
void sortLink(struct HuffNode *head)
{
struct HuffNode *HuffHead = head,*Head = head, *temp;
int flag = NodeNum;
while(flag)
{
while(HuffHead != NULL)
{
temp = HuffHead;
if(temp->Next !=NULL)
{
if((temp->gailv) > (temp->Next->gailv))
{
swapNode(temp, temp->Next);
}
}
HuffHead = HuffHead->Next;
}
HuffHead = head;
flag--;
}
}
struct HuffNode *creatTree(struct HuffNode *head)
{
struct HuffNode *HuffHead = head, *temp;
int flag = NodeNum;
while(flag)
{
temp = HuffHead;
struct HuffNode *NewNode = (struct HuffNode *) malloc(LEN);
NewNode->Next = temp;
NewNode->code = 0;
NewNode->gailv = temp->gailv + temp->Next->gailv;
NewNode->Lchild = temp;
NewNode->Lchild->Parent = NewNode;
NewNode->Rchild = temp->Next;
NewNode->Rchild->Parent = NewNode;
temp->Next->code = 1;
NewNode->Next = temp->Next->Next;
temp->Next->Next= NULL;
temp->Next = NULL;
//printf("The prabobility is : %7.4f and the code is :%d\n", NewNode->gailv, NewNode->code);
//printf("The prabobility of Lchild is : %7.4f and the code is :%d\n", NewNode->Lchild->gailv, NewNode->Lchild->code);
//printf("The prabobility of Rchild is : %7.4f and the code is :%d\n", NewNode->Rchild->gailv, NewNode->Rchild->code);
HuffHead = NewNode;
sortLink(HuffHead);
flag--;
}
printf("\nCreat HuffTree Succeed!\n");
head = HuffHead;
return head;
}
void printTree(struct HuffNode *head)
{
struct HuffNode *HuffHead = head;
if(HuffHead != NULL)
{
printf("gailv: %7.4f code: %d\n", HuffHead->gailv, HuffHead->code);
printTree(HuffHead->Lchild);
printTree(HuffHead->Rchild);
}
}
void printCode(struct HuffNode *leaf)
{
struct HuffNode *HuffHead = leaf;
int a[NodeNum] = {0}, i = 0, j=0;
printf("gailv: %7.4f code:", HuffHead->gailv);
//printf(" the parent of %7.4f is %7.4f Huffcode:", HuffHead->gailv, HuffHead->Parent->gailv);
while(HuffHead->gailv != 1.0)
{
a[i++] = HuffHead->code;
HuffHead = HuffHead->Parent;
}
for(j=i-1; j>=0; j--)
{
printf("%d ", a[j]);
}
/*
while(HuffHead ->gailv != 10)
{
printf("%d ", HuffHead->code);
HuffHead = HuffHead->Parent;
}*/
printf("\n");
}
void printHuffCode(struct HuffNode *head) //打印的思路是这样的,首先从 根节点遍历到叶子节点,,之后再从叶子节点遍历回根节点,
{ //把编码存在一个数组中,再打印这个数组,即 printCode(的功能)
struct HuffNode *HuffHead = head;
if(HuffHead != NULL)
{
if(HuffHead->Lchild == NULL)
{
//printf("gailv: %7.4f code: %d\n", HuffHead->gailv, HuffHead->code);
printCode(HuffHead);
printf("\n");
}
printHuffCode(HuffHead->Lchild);
printHuffCode(HuffHead->Rchild);
}
}
void destroy(struct HuffNode **head)
{
if(*head != NULL)
{
destroy(&(*head)->Lchild);
destroy(&(*head)->Rchild);
// printf(" before free gailv is %f !", (*head)->gailv);
free(*head);
// printf(" Free Succeed!\n");
*head = NULL;
}
}
int main()
{
struct HuffNode *head, *HuffHead;
printf("\n^-^ Welcome come to Huffman Code\n\n");
head = creatLink();
if(head == NULL)
{
system("pause");
return 1;
}
printf("\nThe original link is:\n");
printLink(head);
HuffHead = head;
sortLink(head);
printf("\nThe sort link is:\n");
printLink(head);
printf("\n\n");
head = creatTree(head);
//printf("gailv: %7.4f code: %d\n", head->gailv, head->code);
printTree(head);
printf("\n\n");
printf("The Huffcode is: \n");
printHuffCode(head);
/*
while(head->Parent != NULL)
{
freeTree(head);
}*/
destroy(&head);
system("pause");
return 0;
}
运行截图如下:

