最近完成一个数据结构的作业,哈夫曼编码,实现了
1.查看字母的哈夫曼码
2.哈夫曼码转文字
3.文字转哈夫曼码
这几个功能
哈夫曼码主要用于压缩编码,将字符用二进制(0,1)编码代替,能过使出现概率大的字母的二进制码短,而我们会根据字符的出现概率给各个字符赋一个“权重”,再根据权重构造一个二叉树
核心便是如何构造这个哈夫曼二叉树
那么二叉树的结点结构要有4个元素weight(权重),left(左孩子),right(右孩子),parent(双亲结点)
首先假设我们有一个集合{2,4,5,3}即4个权重
1.选取两个最小的权重(2,3)构成二叉树最底部的叶子,它们的和是他们的parent
集合也就成了 {4,5,5}
2.重复第一步在4 ,5 ,5中选取两个较小的(优先选取还未在树上的4,5),集合变为{9,5}
当然这个代码写得很渣,有一种C语言风格的C++,之后肯定会慢慢地改正过来
1.查看字母的哈夫曼码
2.哈夫曼码转文字
3.文字转哈夫曼码
这几个功能
哈夫曼码主要用于压缩编码,将字符用二进制(0,1)编码代替,能过使出现概率大的字母的二进制码短,而我们会根据字符的出现概率给各个字符赋一个“权重”,再根据权重构造一个二叉树
核心便是如何构造这个哈夫曼二叉树
那么二叉树的结点结构要有4个元素weight(权重),left(左孩子),right(右孩子),parent(双亲结点)
首先假设我们有一个集合{2,4,5,3}即4个权重
1.选取两个最小的权重(2,3)构成二叉树最底部的叶子,它们的和是他们的parent
集合也就成了 {4,5,5}
2.重复第一步在4 ,5 ,5中选取两个较小的(优先选取还未在树上的4,5),集合变为{9,5}
3,重复以上二叉树也就成了
Talk is cheap,show you the code //我的环境是VS2013
// 哈夫曼.cpp : 定义控制台应用程序的入口点。
//
#include "fstream"
#include "iostream"
#include "string"
#define MAX 53
using namespace std;
double w[1000];
string low = "0";
string high = "1";
string Code[1000];
class Huffman_tree
{
public:
void choose(Huffman_tree *h, int n, int &num_1, int &num_2);
Huffman_tree* build_tree(Huffman_tree* &h, double *number, int n);
friend void be_code();
friend void coding(Huffman_tree *T, string code, int n);
friend void de_code(Huffman_tree *T, string code, int &n);
friend void show(Huffman_tree *T);
Huffman_tree()
{
parent = NULL;
left = NULL;
right = NULL;
}
private:
Huffman_tree *left;
Huffman_tree *right;
double weight;
int parent;
};
void Huffman_tree::choose(Huffman_tree *h, int n, int &num_1, int &num_2) //给哈夫曼树各个叶子结点选择权重
{
double m1, m2;
int i = 0;
int j = 0;
for (i = 0; i < n; i++)
{
if (h[i].parent == NULL)
{
m1 = h[i].weight;
num_1 = i;
j = i++;
break;
}
}
for (i = j; i < n; i++)
{
if (h[i].parent == NULL)
{
m2 = h[i].weight;
num_2 = i;
}
}
for (int i = j; i < n; i++)
{
if (h[i].parent == NULL&&i != num_1&&i != num_2)
{
if (h[i].weight < m1)
{
m2 = m1;
num_2 = num_1;
m1 = h[i].weight;
num_1 = i;
}
else if (h[i].weight < m2)
{
m2 = h[i].weight;
num_2 = i;
}
}
}
}
Huffman_tree* Huffman_tree::build_tree(Huffman_tree* &h, double *number, int n) //构造哈夫曼树
{
int i, m,num1, num2;
Huffman_tree *p;
if (n < 2) return NULL;
m = 2 * n - 1;
h = new Huffman_tree[m];
p = h;
for (i = 0; i < n; ++i, ++p)
p->weight = number[i];
for (i = n; i < m; i++)
{
choose(h, i, num1, num2);
h[i].left = &h[num1];
h[i].right = &h[num2];
h[num1].parent = i;
h[num2].parent = i;
h[i].weight = h[num1].weight + h[num2].weight;
}
return &h[m - 1];
}
void coding(Huffman_tree *T, string code, int n) //给各个字母编码
{
if (T != NULL)
{
string temp = code;
code = code + low;
if (T->left == NULL&&T->right == NULL)
for (int i = 0; i < n; i++)
{
if (T->weight == w[i])
{
Code[i] = temp;
}
}
coding(T->left, code, n);
code = temp;
code = code + high;
coding(T->right, code, n);
}
}
bool read_file() //从文件中读取各个字母的概率
{
double weight = 0;
ifstream infile;
infile.open("probability.txt", ios::in);
if (!infile) cout << "Wrong" << endl;
for (int i = 0; i < MAX; i++)
{
infile >> w[i];
weight = weight + w[i];
}
if ((int)weight != 1)
{
cout << "您的概率相加不等于1" << endl;
return 0;
}
else
return 1;
}
void de_code(Huffman_tree *T,string code,int &n) //哈夫曼码转文字的递归算法,直接递归遍历哈夫曼树
{
if (T != NULL)
{
if ((T->left == NULL&&T->right == NULL) || code[n] == '#')
{
for (int j = 0; j < MAX; j++)
{
if (T->weight == w[j])
{
if (j == 0) cout << (char)32;
else if (j < 27) cout << (char)(j + 64);
else cout << (char)(j + 70);
}
}
}
else
{
if (code[n] == '0')
{
n = n + 1;
de_code(T->left, code, n);
}
else
{
n = n + 1;
de_code(T->right, code, n);
}
}
}
}
void show_word(Huffman_tree *root) // 哈夫曼转文字递归算法的调用程序
{
string code;
int temp;
int m = 0;
system("cls");
cout << " 1. 键入 " << endl;
cout << " 2. 读取文件 " << endl;
cin >> temp;
if (temp == 1)
{
cout << "请输入哈夫曼码,以#结尾" << endl;
cin >> code;
while (code[m] != '#')
{
de_code(root, code, m);
}
}
if (temp == 2)
{
ifstream infile;
infile.open("H.txt", ios::in);
infile >> code;
cout<<"从H.txt文件中读取"<<endl;
while (code[m] != '#')
{
de_code(root, code, m);
}
infile.close();
}
}
void show_code(Huffman_tree *root) // 展示字符的哈夫曼码
{
char word;
int i, j;
string s, t;
ofstream Outfile;
Outfile.open("code.txt", ios::out);
coding(root, s, MAX);
cout << "各个字符的哈夫曼编码为" << endl;
i = 32;
for (j = 0; j < MAX; j++)
{
word = i;
cout << word << "\t" << Code[j] << endl;
Outfile << word << "\t" << Code[j] << endl;
if (i == 32)
i = 64;
if (i == 90)
i = 96;
i++;
}
Outfile.close();
}
void be_code() // 文字转哈夫曼码
{
string word;
ofstream Outfile;
ifstream infile;
Outfile.open("result.txt", ios::out);
int n = 0;
system("cls");
cout << "请输入一段话,以#结束,空格用_(下划线)代替)" << endl;
cin >> word;
while (word[n] != '#')
{
int i = word[n];
if (word[n] == '_') i = 32;
if (i == 32)
{
cout << Code[0];
Outfile << Code[0];
}
else if (i < 91)
{
cout << Code[i - 64];
Outfile << Code[i - 64];
}
else
{
cout << Code[i - 70];
Outfile << Code[i - 70];
}
n++;
}
}
void caidan() //由于是课程设计的作业,得有个给老师看的界面
{
cout << "*************************************************************************" << endl;
cout << "* 1.查看哈夫曼码 *" << endl;
cout << "* 2.哈夫曼码转文字 *" << endl;
cout << "* 3.文字转哈夫曼码 *" << endl;
cout << "* 4.退出 *" << endl;
cout << "*************************************************************************" << endl;
}
int main()
{
int temp = 0;
if (read_file())
{
Huffman_tree *buff = new Huffman_tree;
Huffman_tree *root;
root = buff->build_tree(buff, w, MAX);
show_code(root);
system("cls");
while (temp != 4)
{
system("cls");
caidan();
cin >> temp;
switch (temp)
{
case 1:show_code(root); break;
case 2:show_word(root); break;
case 3:be_code(); break;
default: break;
}
system("pause");
}
}
return 0;
}
当然这个代码写得很渣,有一种C语言风格的C++,之后肯定会慢慢地改正过来