数据结构上机作业3-哈夫曼编码

1.问题描述

从键盘接收一串电文字符,输入对应的Huffman编码。同时,能翻译由Huffman编码生成的代码串,输出对应的电文字符串。

2.设计要求

1) 构造一棵 Huffman树。
2) 实现Huffman编码,并用Huffman编码生成的代码串进行译码。
3) 程序中字符和权值是可变的,实现程序的灵活性。

3.代码实现

参考文章:
http://blog.csdn.net/TW_345/article/details/50096819
http://blog.csdn.net/u010366748/article/details/50773903

#include <stdio.h>
#include<stdlib.h>
#include <string.h>

#define MAXBIT      100
#define MAXVALUE  10000
#define MAXLEAF     30
#define MAXNODE    MAXLEAF*2 -1

typedef struct
{
    int bit[MAXBIT];//存放 0或1 ,即根据左右顺序来进行编码
    int start;//走过的次数
} HCodeType;        /* 编码结构体 */

typedef struct
{
    int weight;
    int parent;
    int lchild;
    int rchild;
    int value;
} HNodeType;        /* 结点结构体 */

//构造一个哈夫曼树,n为叶子数
void createHuffmanTree(HNodeType HuffNode[MAXNODE],int n)
{
    int i,j;//用于循环遍历
    int m1,m2;//构造哈夫曼树中最小的两个结点的权值
    int x1,x2;//构造哈夫曼树中最小的两个结点的序号

    /*初始化存放哈夫曼树数组 HuffNode[] 中的节点*/
    //如果有n个叶子,则总共有 2n-1 个结点
    for(i=0;i<2*n-1;i++)
    {
        HuffNode[i].weight = 0;//权值
        HuffNode[i].parent =-1;//等于-1表示无父结点,下面同
        HuffNode[i].lchild =-1;
        HuffNode[i].rchild =-1;
        HuffNode[i].value=i; //实际值,可根据情况替换为字母
    }
    //给n个叶子结点赋权值
    for(i=0;i<n;i++)
    {
        printf("请输入第%d个叶子的权值:",i);
        scanf("%d",&HuffNode[i].weight);
    }

    /*构建哈夫曼树*/
    for(i=0;i<n-1;i++)
    {
        m1=m2=MAXVALUE;//m1 m2存放两个无父结点且结点权值最小的两个结点
        x1=x2=0;//x1 x2 存放对应的序号
        for(j=0;j<n+i;j++)
        {
            //先不断循环if语句,直到m1取到最小值,且左边小右边大
            if(HuffNode[j].weight<m1 && HuffNode[j].parent==-1)
            {
                m2=m1;
                x2=x1;
                m1=HuffNode[j].weight;
                x1=j;
            }
            //m1取到最小值后,无论如何第一个if都不会成立,此时elseif开始运行
            else if (HuffNode[j].weight < m2 && HuffNode[j].parent==-1)
            {
                m2=HuffNode[j].weight;
                x2=j;
            }
        }
        HuffNode[x1].parent  = n+i;
        HuffNode[x2].parent  = n+i;
        HuffNode[n+i].weight = HuffNode[x1].weight + HuffNode[x2].weight;
        HuffNode[n+i].lchild = x1;
        HuffNode[n+i].rchild = x2;

        printf ("x1.weight and x2.weight in round %d: %d, %d\n", i+1, HuffNode[x1].weight, HuffNode[x2].weight);  /* 用于测试 */

        printf ("\n");
    }
}

/*解码,string数组是要破解的编码;Buf[];n是叶子数*/
void decoding(char string[], HNodeType Buf[],int Num)
{
    int i,tmp=0,code[1024];//i用于遍历
    int m=2*Num-1;//m代表结点数
    char *nump;
    char num[1024];

    //
    for(i=0;i<strlen(string);i++)
    {
        if(string[i]=='0')
            num[i]=0;
        else
            num[i]=1;
    }

    i=0;
    nump=&num[0];//nump指向编码

    while(nump<(&num[strlen(string)]))
    {
        tmp=m-1;
        while((Buf[tmp].lchild!=-1)&&(Buf[tmp].rchild!=-1))
        {
            if(*nump==0)
            {
                tmp=Buf[tmp].lchild ;
            }
            else tmp=Buf[tmp].rchild;
            nump++;
        }
        printf("%d",Buf[tmp].value);
    }

}

int main()
{
    HNodeType HuffNode[MAXNODE];//定义一个结构体数组
    HCodeType HuffCode[MAXLEAF],cd;//存放一个编码结构体数组,同时定义个临时变量存放解码信息
    int i, j, c, p, n;//i,j用于循环;c表示孩子结点,p代表父结点,n表示叶子数
    char pp[100];
    printf("请输入叶子数n:");
    scanf("%d",&n);
    createHuffmanTree(HuffNode,n);

    /*开始进行编码*/
    for(i=0;i<n;i++)
    {
        cd.start=n-1;//一条二叉树,最多不过n-1次路
        c=i;//c指向0
        p=HuffNode[c].parent;//p指向0的父结点
        while(p!=-1)
        {
            /*cd用于临时存储编码,且由于从子结点向上逆推,故倒着存储*/
            if(HuffNode[p].lchild==c)
                cd.bit[cd.start]=0;//如果是左结点,就保存一个 0
            else
                cd.bit[cd.start]=1;//不然,就保存一个 1
            cd.start--;//start往前推一位
            c=p;//向上遍历,直到根结点
            p=HuffNode[c].parent;
        }

        for(j=cd.start+1;j<n;j++)//因为在上面的while中,到了根结点后,start减了一下,故要+1
            HuffCode[i].bit[j]=cd.bit[j];//保存编码

        HuffCode[i].start=cd.start;//保存每个编码的起始位置
    }

    /*输出哈夫曼编码*/
    for(i=0;i<n;i++)
    {
        printf("第%d个叶子的哈夫曼编码是:",i);
        for(j=HuffCode[i].start+1;j<n;j++)
        {
            printf("%d",HuffCode[i].bit[j]);
        }
        printf(" start:%d",HuffCode[i].start);
        printf("\n");
    }

    printf("请输入要破解的编码:");
    scanf("%s",&pp);
    decoding(pp,HuffNode,n);
    getchar();
    return 0;
}

猜你喜欢

转载自blog.csdn.net/zyf2333/article/details/78565901