huffman编码

总所周知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;    
}



运行截图如下:
每日算法之--------------huffman编码 - vanpire110 - vanpire110的博客
 
每日算法之--------------huffman编码 - vanpire110 - vanpire110的博客
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值