利用优先队列写哈夫曼树

数据结构中,对于用哈夫曼树写优先队列,相信网上有很多种方法,可是我认为,我这可能是最简单的方法了。

我利用了优先队列,建立哈夫曼树的时候只要在哈夫曼树里面弹出两个根节点,进行频率的计算,然后把新的根节点压入新的队列(链表)里面,当然,在写压入函数的时候要写排序,这样,就可以在压入的时候进行排序,下次再弹出的时候就可以继续弹出两个最小的了!

对于上一篇的优先队列,因为要把之前测试的int类型改为Huffamtree类型,所以,读入部分要进行适当的修改

》》》》》》》

///将数据读入pq
void ReadToPQueue(PQueue &pq,char *text)
{

    PQNode *sq;
    int flag = 1;

    pq.h = new PQNode;
    pq.h->next=NULL;
    pq.len=0;
    int len = strlen(text);
    for (int i = 0;i<len;i++)
    {
        for (sq = pq.h->next ; sq ; sq = sq->next)
        {
            if (sq->data->ch == *(text+i))
            {
                flag = 0;
                sq->data->freq++;
            }
        }

        if (flag == 1)
        {
            PQElemType e = new HuffanTreeNode();
            e->ch = *(text+i);
            e->freq = 1;
            e->lch = NULL;
            e->rch = NULL;
            PQNode *pqNew=new PQNode;
            pqNew->data = e;
            pqNew->next = pq.h->next;
            pq.h->next = pqNew;
            pq.len++;
        }
        flag = 1;
        //cout  << "hello world ";
    }
    for (sq = pq.h->next ; sq ; sq = sq->next)
    {
        cout << sq->data->ch <<"==="<<sq->data->freq<<endl;
    }
    return ;
}

这是剩余的结构体的类型的定义

》》》》》》》

/*
 huffmanTree.h
关于huffman树(即二叉树)的类型定义
huffman代码表的类型定义
*/

#ifndef HUFFMAN_H_INCLUDED
#define HUFFMAN_H_INCLUDED

const int CHARCNT = 30; //最多30个不同的字符
struct HuffanTreeNode
{
    char ch;  // 字符
    int freq; // 出现频率
    HuffanTreeNode *lch;
    HuffanTreeNode *rch;
};

// 定义huffman树
typedef HuffanTreeNode *HuffmanTree;

//字符-代码项类型
struct Code
{
    char ch;
    int freq;
    char *code;
};

// 字符-代码表类型
struct HCTalbe
{
    Code  codeTable[CHARCNT];
    int   len;
};


#endif // HUFFMAN_H_INCLUDED

/*
huffmanCode.h
关于生成huffman树,解码,译码等操作的声明
*/

#ifndef HUFFMANCODE_H_INCLUDED
#define HUFFMANCODE_H_INCLUDED

#include "huffmanTree.h"
#include "priorityQueue.h"


/// 建huffman树
HuffmanTree CreateHuffmanTree(PQueue &pq);

/// 由huffman树bt,生成huffman编码表hc
int GenHuffmanCode(HuffmanTree bt, HCTalbe &hc);

///输出huffman表
void PrintHuffmanCode(HCTalbe hc);


/**解码:返回解码后的报文
 * @codeMsg 编码信息
 * @ht   Huffman编码表*/
void Decode(HuffmanTree ht ,char *text);


/**编码:返回以Huffman编码的编码文
 * @msg  待编码的信息
 * @ht   Huffman编码表*/
void Encode(char *msg, HCTalbe ht);

#endif // HUFFMANCODE_H_INCLUDED

下面是主体部分的代码,也就是cpp,精髓所在

》》》》》》》》

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include "huffmanTree.h"
#include "priorityQueue.h"
#include "huffmanCode.h"
#include <string.h>

using namespace std;

/// 建huffman树
HuffmanTree CreateHuffmanTree(PQueue &pq)
{

    HuffmanTree bt;

    while(pq.len>1)
    {
        bt = new HuffanTreeNode;
        HuffmanTree t1 = Pop(pq);//删除一个节点,作为新bt的左子节点
        HuffmanTree t2 = Pop(pq);//右子节点

        bt->lch = t1;
        bt->rch = t2;
        bt->freq = t1->freq + t2->freq;//计算最后权值
        Push(pq,bt);//将根插入优先队列
    }
    bt = Pop(pq);
    return bt;
}

/// 由huffman树bt,生成huffman编码表hc
int GenHuffmanCode(HuffmanTree bt, HCTalbe &hc,int depth)
{
    static char temp[100];
    static int wpl = 0;
    //hc.len = 0;

    if(bt==NULL)
        return 0 ;

    if(bt->lch==NULL && bt->rch==NULL )
    {
        temp[depth] = '\0';
        char *p = new char[strlen(temp)];

        strcpy(p,temp);
        hc.codeTable[hc.len].ch = bt->ch;
        hc.codeTable[hc.len].code = p;
        hc.len++;
        wpl += (depth+1) * bt->freq;
        return wpl;
    }

    temp[depth] = '0';
    GenHuffmanCode(bt->lch, hc, depth+1) ;

    temp[depth] = '1';
    GenHuffmanCode(bt->rch, hc, depth+1);
}

int GenHuffmanCode(HuffmanTree bt, HCTalbe &hc )
{
    hc.len = 0;
    return GenHuffmanCode(bt, hc, 0);
}

///输出huffman表
void PrintHuffmanCode(HCTalbe hc)
{
    //通过二叉树bt(视为huffman树),生成各叶子的huffman码

    for(int i=0; i<hc.len; i++)
        cout << hc.codeTable[i].ch   << ":  "
             << hc.codeTable[i].code << endl;
}


/**解码
 * @codeMsg 编码信息
 * @ht   Huffman编码表*/
void Decode(HuffmanTree ht,char *text)
{
    static int i = 0;
    PQElemType h ;
    static char temp[100];
    static int depth = 0;
    h = ht;
    int m = strlen(text);
    for (i = 0; i<m; i++)
    {
        //h = ht;  //不能放在这里,切记,否则就是每遍历一个节点(包括不是叶子的节点)都会回头。
            if (*(text+i) == '0')
            {
                h = h->lch;
                if(h->lch==NULL && h->rch==NULL )
                {
                    temp[depth++] = h->ch;
                    cout << h->ch;
                    h = ht;  ///只有找到叶子节点才返到头节点
                }

            }
            if (*(text+i) == '1')
            {
                h = h->rch;
                if(h->lch==NULL && h->rch==NULL )
                {
                    cout <<h->ch;
                    temp[depth++] = h->ch;
                   h = ht;
                }

            }
            temp[depth] = '\0';
    }
}


/**编码
 * @msg  待编码的信息
 * @ht   Huffman编码表*/
void Encode(char *msg, HCTalbe ht)
{
    int m = strlen (msg);
    for (int i = 0; i < m ; i++)
    {
        for (int j = 0; j < ht.len ; j++)
        {
            if (*(msg+i) == ht.codeTable[j].ch)
            {
                cout << ht.codeTable[j].code;
            }
        }
    }
}




代码差不多就是这样,下面是运行结果
》》》》》》》》》》》

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值