打印

请帮我分析下,一个关于数据压缩的程序,有很多不懂。谢

[复制链接]
1329|1
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
mingyuekd|  楼主 | 2008-11-7 18:01 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
#include <stdio.h>
#include <stdlib.h>

#define TRUE 1
#define FALSE 0

// 编码的最大位数
#define MAXBITS        50
// 最大的字符数
#define MAXSYMBS    MAXBITS
// 树中的最大节点
#define MAXNODES    2 * MAXSYMBS-1

struct CodeType {
    int nBits[MAXBITS];
    int nStartPos;
};

struct NodeType {
    int nFrequency;
    int nParent;
    int iSLeft;
};

// 队列的插入删除处理
void QueueInsert(int nWhich);
int QueueDelete(void);

// 定义全局变量
struct NodeType node[MAXNODES];
// 队列最初位空
int rootnodes = -1;

void main(void)
{
    struct CodeType cd, code[MAXSYMBS];
    int i;
    int nSymbolsNum;
    int nBitCount;
    int nNextNode;
    int nLeftNode, nRightNode;
    int root;
    int thisnode;
    char symbol, alphabet[MAXSYMBS];

    // 清空字符数组
    for(i = 0; i < MAXSYMBS; i++)
    {
        alphabet = ' ';
    }

    /*// 有多少个字符
    printf("Please input char's count\n");
    scanf("%d", &nSymbolsNum);

    printf("Please input char and frequencies\n");
    // 得到数据和每个字符的频率
    for(i = 0; i < nSymbolsNum; i++)
    {
        scanf("%s%d", &symbol, &node.nFrequency);
        QueueInsert(i);
        alphabet = symbol;
    }*/

    //构造信源数据
    nSymbolsNum = 3;
    alphabet[0] = 'a';
    node[0].nFrequency = 8;
    QueueInsert(0);
    alphabet[1] = 'b';
    node[1].nFrequency = 2;
    QueueInsert(1);
    alphabet[2] = 'c';
    node[2].nFrequency = 5;
    QueueInsert(2);

    // 形成Huffman树
    for(nNextNode =  nSymbolsNum;
        nNextNode < 2 * nSymbolsNum - 1;
        nNextNode ++)
    {
        nLeftNode = QueueDelete();
        nRightNode = QueueDelete();
        
        // 形成新的树,作为子节点
        node[nLeftNode].nParent = nNextNode;
        node[nRightNode].nParent = nNextNode;
        node[nLeftNode].iSLeft = TRUE;
        node[nRightNode].iSLeft = FALSE;
    
        // 父节点的频率是两个子节点频率之和
        node[nNextNode].nFrequency = 
            node[nLeftNode].nFrequency + node[nRightNode].nFrequency;
        
        //插入节点
        QueueInsert( nNextNode);
    }

    // 根节点
    root = QueueDelete();
    // 根据树进行编码
    for(i = 0; i < nSymbolsNum; i++)
    {
        // 搜索的初始点
        cd.nStartPos = MAXBITS;

        // 对树进行遍历,对内容进行编码
        thisnode = i;
        while(thisnode != root)
        {
            --cd.nStartPos;
            cd.nBits[cd.nStartPos] = node[thisnode].iSLeft ? 0 : 1;
            thisnode = node[thisnode].nParent;
        }

        // 内容拷贝
        for(nBitCount = cd.nStartPos; nBitCount < MAXBITS; nBitCount++)
        {
            code.nBits[nBitCount] = cd.nBits[nBitCount];
        }
        code.nStartPos = cd.nStartPos;
    }

    for(i = 0; i < nSymbolsNum; i++)
    {
        printf("\n%c %d ", alphabet, node.nFrequency);
        for(nBitCount = code.nStartPos; nBitCount < MAXBITS; nBitCount++)
        {
            printf("%d", code.nBits[nBitCount]);
        }
        printf("\n");
    }
}
// 将节点插入到队列里
void QueueInsert(int nWhich)
{
    int thisnode, previous;
    // 队列是否为空
    if(rootnodes == -1)
    {
        // 空队列
        node[nWhich].nParent = -1;
        rootnodes = nWhich;
    }
    else
    {
        thisnode = rootnodes; 
        previous = -1;
        //搜索大的节点
        while((thisnode != -1) && 
            (node[thisnode].nFrequency < node[nWhich].nFrequency))
        {
            previous = thisnode;
            thisnode = node[thisnode].nParent;
         }

        // 连接到第一个大的节点
        node[nWhich].nParent = thisnode;
        if(previous != -1)
        {
            // 拷贝
            node[previous].nParent = nWhich;
        }
        else
        {
            // 插入到开始位置
            rootnodes = nWhich;
        }
    }
}

//从优先队列里去掉第一个结点
int QueueDelete(void)
{
    int thisnode = rootnodes;
    rootnodes = node[thisnode].nParent;
    return thisnode;
}
    

相关帖子

沙发
xwj| | 2008-11-7 18:09 | 只看该作者

建议去找JPEG详解看看,对Huffman编码和压缩有详细的说明

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

58

主题

151

帖子

0

粉丝