数据结构中,对于用哈夫曼树写优先队列,相信网上有很多种方法,可是我认为,我这可能是最简单的方法了。
我利用了优先队列,建立哈夫曼树的时候只要在哈夫曼树里面弹出两个根节点,进行频率的计算,然后把新的根节点压入新的队列(链表)里面,当然,在写压入函数的时候要写排序,这样,就可以在压入的时候进行排序,下次再弹出的时候就可以继续弹出两个最小的了!
对于上一篇的优先队列,因为要把之前测试的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; } } } }
代码差不多就是这样,下面是运行结果
》》》》》》》》》》》