編程實現哈夫曼編碼
1. c或c++ 實現 哈夫曼編碼 最優字元串編碼
#include <iostream>
#include <queue>
#include <vector>
#include <map>
#include <string>
using namespace std;
class Node {
public:
char c; //表示字元
int frequency; //表示該字元出現的次數或頻率
Node *left;
Node *right;
Node(char _c, int f, Node *l = NULL, Node *r = NULL)
:c(_c), frequency(f), left(l), right(r) { }
bool operator<(const Node &node) const { //重載<運演算法以至於在加入優先隊列的時候決定如何處理結點位置
return frequency > node.frequency;
}
};
void initNode(priority_queue<Node> &q, int nodeNum) {
char c;
int frequency;
for (int i = 0; i < nodeNum; i++) {
cout << "輸入字元和結點出現的次數: ";
cin >> c >> frequency;
Node node(c, frequency);
q.push(node);
}
}
void showNode(priority_queue<Node> q) {
while (!q.empty()) {
Node node = q.top(); q.pop();
cout << node.c << ", " << node.frequency << endl;
}
}
//構造哈夫曼樹
void huffmanTree(priority_queue<Node> &q) {
while (q.size() != 1) {
Node *left = new Node(q.top()); q.pop();
Node *right = new Node(q.top()); q.pop();
Node node('R', left->frequency + right->frequency, left, right);
q.push(node);
}
}
// 列印哈夫曼編碼
void huffmanCode(Node *root, string &prefix, map<char, string> &result) {
string m_prefix = prefix;
if (root->left == NULL)
return;
//處理左子樹
prefix += "0";
//如果是葉子結點則輸出,否則遞歸列印左子樹
if (root->left->left == NULL)
result[root->left->c] = prefix;
//cout << root->left->c << ": " << prefix << endl;
else
huffmanCode(root->left, prefix, result);
//還原原來的路徑,回溯
prefix = m_prefix;
//處理右子樹
prefix += "1";
//如果是葉子結點,則輸出, 否則遞歸列印右子樹
if (root->right->right == NULL)
result[root->right->c] = prefix;
//cout << root->right->c << ": " << prefix << endl;
else
huffmanCode(root->right, prefix, result);
}
void testResult(map<char, string> result) {
//迭代map容器
map<char, string>::const_iterator it = result.begin();
while (it != result.end()) {
cout << it->first << ": " << it->second << endl;
++it;
}
}
int main() {
priority_queue<Node> q;
int nodeNum;
//初始化字元信息
cout << "請輸入結點個數: ";
cin >> nodeNum;
initNode(q, nodeNum);
//showNode(q);
//構造哈夫曼樹
huffmanTree(q);
//構造哈夫曼編碼
Node root = q.top();
string prefix = "";
map<char, string> result;
huffmanCode(&root, prefix, result);
//檢驗結果是否正確
testResult(result);
return 0;
}
2. 哈夫曼編碼的程序實現
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#define M 100
typedef struct Fano_Node
{
char ch;
float weight;
}FanoNode[M];
typedef struct node
{
int start;
int end;
struct node *next;
}LinkQueueNode;
typedef struct
{
LinkQueueNode *front;
LinkQueueNode *rear;
}LinkQueue;
//建立隊列
void EnterQueue(LinkQueue *q,int s,int e)
{
LinkQueueNode *NewNode;
//生成新節點
NewNode=(LinkQueueNode*)malloc(sizeof( LinkQueueNode ));
if(NewNode!=NULL)
{
NewNode->start=s;
NewNode->end=e;
NewNode->next=NULL;
q->rear->next=NewNode;
q->rear=NewNode;
}
else
{
printf(Error!);
exit(-1);
}
}
//按權分組
void Divide(FanoNode f,int s,int *m,int e)
{
int i;
float sum,sum1;
sum=0;
for(i=s;i<=e;i++)
sum+=f[i].weight;//
*m=s;
sum1=0;
for(i=s;i<e;i++)
{
sum1+=f[i].weight;
*m=fabs(sum-2*sum1)>fabs(sum-2*sum1-2*f[i+1].weight)?(i+1):*m;
if(*m==i) break;
}
}
void main()
{
int i,j,n,max,m,h[M];
int sta,end;
float w;
char c,fc[M][M];
FanoNode FN;
LinkQueueNode *p;
LinkQueue *Q;
//初始化隊Q
Q=(LinkQueue *)malloc(sizeof(LinkQueue));
Q->front=(LinkQueueNode*)malloc(sizeof(LinkQueueNode));
Q->rear=Q->front;
Q->front->next=NULL;
printf( ***FanoCoding***
);
printf(Please input the number of node:);
//輸入信息
scanf(%d,&n);
//超過定義M,退出
if(n>=M)
{
printf(>=%d,M);
exit(-1);
}
i=1; //從第二個元素開始錄入
while(i<=n)
{
printf(%d weight and node:,i);
scanf(%f %c,&FN[i].weight,&FN[i].ch);
for(j=1;j<i;j++)
{
if(FN[i].ch==FN[j].ch)//查找重復
{
printf(Same node!!!
); break;
}
}
if(i==j)
i++;
}
//排序(降序)
for(i=1;i<=n;i++)
{
max=i+1;
for(j=max;j<=n;j++)
max=FN[max].weight<FN[j].weight?j:max;
if(FN[i].weight<FN[max].weight)
{
w=FN[i].weight;
FN[i].weight=FN[max].weight;
FN[max].weight=w;
c=FN[i].ch;
FN[i].ch=FN[max].ch;
FN[max].ch=c;
}
}
for(i=1;i<=n;i++) //初始化h
h[i]=0;
EnterQueue(Q,1,n); //1和n進隊
while(Q->front->next!=NULL)
{
p=Q->front->next; //出隊
Q->front->next=p->next;
if(p==Q->rear)
Q->rear=Q->front;
sta=p->start;
end=p->end;
free(p);
Divide(FN,sta,&m,end); /*按權分組*/
for(i=sta;i<=m;i++)
{
fc[i][h[i]]='0';
++h[i];
}
if(sta!=m)
EnterQueue(Q,sta,m);
else
fc[sta][h[sta]]='