哈夫曼编码与译码器

题目:哈夫曼编译码系统(Huffman)

① 问题描述:给定n个字符的全值数组w,根据哈夫曼编码与译码规则,实现一个哈夫曼编译码系统(利用实验指导书上的27个字符的数据进行实验)。

② 利用顺序表存储Huffman树,编码结果的存储方式采用书上的结构。

③ Huffman树的构造约定如下:

l       根的权值较小的子树作为左子树,当权值相等时,先生成的作为左子树;

l       按照结点的产生次序选择权值较小的两棵子树构造Huffman树;

l       从叶子到根逆向求每个字符的Huffman编码,不采用递归方法;

l       从根结点开始实现译码,要求被译码的字符数大于20个字符。

④ 采用文件方式存储n个权值和待翻译的二进制代码,其余的数据或结构均不采用文件存储。

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


int m, s1, s2; // m是总结点个数,s1,s2用于筛选出最小和第二小的两个数

typedef struct
{
    unsigned int weight;
    unsigned int parent, lchild, rchild;
} HTNode, *HuffmanTree;
typedef char* HuffmanCode;
void select(HuffmanTree HT, int nNode) //
{
    int i, j;
    for(i = 1; i <= nNode; i++)
        if(!HT[i].parent)
        {
            s1 = i;
            break;
        }
    for(j = i+1; j <= nNode; j++)
        if(!HT[j].parent)
        {
            s2 = j;
            break;
        }

    for(i = 1; i <= nNode; i++)
        if((HT[i].weight < HT[s1].weight) && (!HT[i].parent) && (s2 != i))
            s1 = i;
    for(j = 1; j <= nNode; j++)
        if((HT[j].weight < HT[s2].weight) && (!HT[j].parent) && (s1 != j))
            s2 = j;
    // 保证s1的weight比s2的小
    if(HT[s1].weight > HT[s2].weight)
    {
        int tmp = s1;
        s1 = s2;
        s2 = tmp;
    }
}

// w[]存放nNode个字符的权值,构造哈夫曼树HT,
// 并求出nNode个字符的哈夫曼编码HC
void HuffmanCoding(HuffmanTree &HT, HuffmanCode HC[], int *w, int nNode)
{
    int i, j;
    char *cd;
    int cdlen;
    if(nNode < 1)
        return;
    m = 2*nNode-1;   //结点数

    //树初始化
    HT = (HTNode*) malloc ((m+1) *sizeof(HTNode));  //0号单元未用
    for(i = 1; i <= nNode; i++)    //初始化
    {
        HT[i].weight = w[i-1];
        HT[i].parent = 0;
        HT[i].lchild = 0;
        HT[i].rchild = 0;
    }
    for(i = nNode+1; i <= m; i++)
    {
        HT[i].weight = 0;
        HT[i].parent = 0;
        HT[i].lchild = 0;
        HT[i].rchild = 0;
    }

    //建立哈弗曼树
    for(i = nNode+1; i <= m; i++)
    {
        select(HT, i-1); //选出权值最小的节点和次小的节点
        HT[s1].parent = i;
        HT[s2].parent = i;
        HT[i].lchild = s1;
        HT[i].rchild = s2;
        HT[i].weight = HT[s1].weight + HT[s2].weight;
        if(i==m)
        {
            printf("结点 weight   parent   lchild   rchild");
            for(j = 1; j <= i; j++)
                printf("\n%4d%8d%8d%8d%8d", j, HT[j].weight, HT[j].parent, HT[j].lchild, HT[j].rchild);
        }
    }


    //求Huffman树的编码
    cd = (char *) malloc (nNode * sizeof(char));   //分配求编码的工作空间
    cdlen = 0;
    cd[nNode-1]='\0';
    int c,f;
    for(int i=1; i<=nNode; i++)
    {
        cdlen=nNode-1;
        for(c=i,f=HT[i].parent; f!=0; c=f,f=HT[f].parent)
        {
            if(HT[f].lchild==c) cd[--cdlen]='0';
            else cd[--cdlen]='1';
        }
        HC[i]=(char*)malloc((nNode-cdlen)*sizeof(char));
        strcpy(HC[i],&cd[cdlen]);
    }

}


int main()
{
    freopen("in.txt","r",stdin);
    HuffmanTree HT;   // 哈夫曼树
    HuffmanCode *HC;  // 哈夫曼编码
    int *w, nNode, i; // 权值
    puts("输入结点数: ");
    scanf("%d", &nNode);
    HC = (HuffmanCode *) malloc (nNode* sizeof(HuffmanCode));
    w = (int *) malloc (nNode * sizeof(int));
    printf("输入 %d 个结点的对应的权值\n", nNode);
    for(i = 0; i < nNode; i++)
        scanf("%d", &w[i]);
    HuffmanCoding(HT, HC, w, nNode);
    puts("\n各结点的哈夫曼编码为:");
    for(i = 1; i <= nNode; i++)
        printf("%2d ---%4d : %s\n", i, w[i-1], HC[i]);
    getchar();
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值