huffman编码

来源:互联网 发布:手机制作视频的软件 编辑:程序博客网 时间:2024/04/27 08:43
总所周知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 3struct 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;    }



运行截图如下:
每日算法之--------------huffman编码 - vanpire110 - vanpire110的博客
 
每日算法之--------------huffman编码 - vanpire110 - vanpire110的博客
原创粉丝点击