这部分是组长分给我的任务,查了很多资料,下面是代码,恕我愚钝,代码冗长,但结果正确,可供参考
//将待压缩信息输入到“myfile.txt”文件中后,就能建立哈夫曼树,进行哈夫曼编码、压缩、解压,译码,动态哈夫曼编码、压缩、解压和动态哈夫曼树建立成功。
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<fstream>
#include<string>
#include<cstdio>
using namespace std;
void hyasuo();
void hjieguo();
void hjieyasuo();
struct enode
{
char data;
enode* parent;
enode* lenode;
enode* renode;
enode* next;
enode* former;
int num;//权重
enode()
{
data = '\0';
num = 0;
parent = NULL;
lenode = NULL;
renode = NULL;
next = NULL;
former = NULL;
}
};
class trees//哈夫曼编码
{
private:
enode* head;
int num;
enode* rear;
public:
trees()
{
num = 0;
head = new enode;
rear = new enode;
head->next = rear;
rear->former = head;
}
void create(int a,int b)
{
enode* p = new enode;
p->data = a+'a';
p->num = b;
head->next->former = p;
p->next = head->next;
head->next = p;
p->former = head;
}
void encoding()//哈夫曼树
{
while (head->next->next != rear)
{
find();
}
}
void find()//查找第一小与第二小的节点,合并并删除
{
int a = 1000, b = 1000;
enode* p = new enode, * q=new enode, * w=new enode;
p = head->next;
while (p != rear)
{
if (p->num < a)
{
a = p->num;
q = p;
}
p = p->next;
}
p = head->next;
while (p != rear)
{
if (p->num < b && p != q)
{
b = p->num;
w = p;
}
p = p->next;
}
sum(q, w);
}
void sum(enode* &q, enode* &w)
{
enode* e = new enode;
e->num = q->num + w->num;
e->next = head->next;
head->next->former = e;
e->former = head;
head->next = e;
q->parent = e;
w->parent = e;
if (q->num < w->num)
{
e->lenode = q;
e->renode = w;
}
else
{
e->lenode = w;
e->renode = q;
}
delet(w);
delet(q);
}
void delet(enode*& p)
{
if (p != NULL)
{
p->former->next = p->next;
p->next->former = p->former;
}
}
enode*& gethead()
{
return head;
}
void lencoding()//霍夫曼编码部分:这里规定txt文件内容是由26个字符组成,可以根据需要修改一下
{
char a = 'a';
enode* p = new enode;
int b[30], i=0;
enode* q = new enode;
ifstream fp;
ofstream fo;
ofstream ff;
ff.open("哈夫曼编码结果.txt");
fo.open("writefile.txt");
if (!fo)
{
cout << "faile" << endl;
exit(1);
}
for (a = 'a'; a < 'z'; a++)
{
i = 0;
search(head->next, a, p);//搜索哈夫曼树中是否有该字符
if (p->data == a)//有该字符,取得该字符编码
{
fo << a<<endl;
//cout << a << ":";
q = p;
while (q != head->next)
{
if (q->parent->lenode == q)
b[i] = 0;
else
b[i] = 1;
i++;
q = q->parent;
}
i--;
for (i; i >= 0; i--)
{
fo << b[i];
}
fo << endl;
}
}
fp.open("myfile.txt", ios::in);
if (fp.is_open())
{
cout << "success" << endl;
}
fp >> a;
while (!fp.eof())
{
i = 0;
search(head->next, a, p);//搜索哈夫曼树中是否有该字符
if (p->data == a)//有该字符,取得该字符编码
{
//cout << a << ":";
q = p;
while (q != head->next)
{
if (q->parent->lenode == q)
b[i] = 0;
else
b[i] = 1;
i++;
q = q->parent;
}
i--;
for (i; i >= 0; i--)
{
cout << b[i];
ff << b[i];
}
//cout << endl;
}
if (fp.good())
{
fp >> a;
}
}
cout << endl;
ff.close();
fp.close();
fo.close();
}
void search(enode*& p, char a, enode*& q)//搜索节点数据;
{
if (p->data == a)
{
q = p;
}
if (p->lenode != NULL)
search(p->lenode, a, q);
if (p->renode != NULL)
search(p->renode, a, q);
}
void kl(enode*& p)
{
cout << endl;
if (p->data != '\0')
cout << p->data << endl;
if (p->renode != NULL)
{
kl(p->renode);
}
if (p->lenode != NULL)
{
kl(p->lenode);
}
}
void pencoding()
{
ifstream ff;
ff.open("哈夫曼编码解压后修正的信息.txt");
enode* p = new enode;
p=head->next;
char c;
ff >> c;
while (!ff.eof())
{
if (c == '0')
{
p = p->lenode;
}
else
p = p->renode;
if (p->lenode == NULL)
{
cout << p->data;
p = head->next;
}
ff >> c;
}
ff.close();
}
};
struct node//节点定义
{
char data;
node* parent;
node* lnode;
node* rnode;
int num;//序号
int quan;//权重
node()
{
data = '\0';
parent = NULL;
lnode = NULL;
rnode = NULL;
num = -1;
quan = 0;
}
node(char a, node* b, node* c, node* d,int e,int f)
{
data = a;
parent = new node;
parent = b;
lnode = new node;
lnode = c;
rnode = new node;
rnode = d;
num = f;
quan = e;
}
};
class tree//动态哈夫曼编码
{
node* tr;//根
int nodenum;//节点的数目&序号
node* nyt;//动态哈夫曼树的逸出码
public:
tree()
{
nodenum = -1;
tr = new node;
nyt = tr;
}
void creat(char a)//动态哈夫曼树的建立:将输入的字符加入哈夫曼树中,如果树中没有该字符则添加,如果有则对应权重加一;
{
node* p = new node;
search(tr,a,p);//搜索哈夫曼树中是否有该字符
ofstream ff;
ff.open("动态哈夫曼编码结果.txt",ios::out|ios::app);
if (p->data==a )//有该字符,对应权重及其所有父节点权重加一
{
int b[30];
int i = 0;
node* f = p;
while (f != tr)
{
if (f->parent->lnode == f)
{
b[i] = 0;
}
else
{
b[i] = 1;
}
i++;
f = f->parent;
}
i--;
for (i; i >= 0; i--)
{
cout << b[i];
ff << b[i];
}
node* z = new node;
node* q = new node;
q = NULL;
search(tr, p->quan, q, nyt->num);//按照哈夫曼编码原理,将该字符节点与相同权重下编号最大的节点交换,这是寻找相同权重下的最大编码
if (q != NULL&&q->data!=p->data)//找到了最大编号,且不为自己,就将二者交换
{
char ch;
ch = q->data;
q->data = p->data;
p->data = ch;
}
// cout << p<<" " << q << endl;
plusone(q);//所有对应的所有父节点权重加一
}
else//如果哈夫曼树中没有该字符,就把该字符加在原来的nyt节点处
{
int b[30];
int i = 0;
ifstream fp;
string s;
string c ;
c = a;
fp.open("writefile.txt", ios::in);
if (nyt == tr)
{
cout << "0";
ff << "0";
}
else
{
node* f = nyt;
while (f != tr)
{
if (f->parent->lnode == f)
{
b[i] = 0;
}
else
{
b[i] = 1;
}
i++;
f = f->parent;
}
i--;
for (i; i >= 0; i--)
{
cout << b[i];
ff<< b[i];
}
}
while (getline(fp, s))
{
if (s == c)
{
getline(fp, s);
cout << s ;
ff<< s;
}
}
--nodenum;
node* q = new node(a, nyt, NULL, NULL, 1, nodenum);
--nodenum;
node* w = new node('\0', nyt, NULL, NULL, 0, nodenum);
nyt->rnode = q;
nyt->lnode = w;
nyt =w;
plusone(nyt->parent);
}
judge(tr);//判断新树是否符合哈夫曼树的条件——父节点权重大于右孩子权重大于左孩子权重,不满足的话就交换左右孩子位置
ff.close();
}
void judge(node*& p)
{
if (p->lnode != NULL && p->rnode != NULL)
{
if (p->lnode->quan > p->rnode->quan)
{
node* q = p->lnode;
p->lnode = p->rnode;
p->rnode = q;
}
if (p->lnode->lnode != NULL)
{
judge(p->lnode);
}
if (p->rnode->rnode != NULL)
{
judge(p->rnode);
}
}
}
void plusone(node*& p)
{
node* q = p;
while (q != NULL)
{
q->quan+=1;
q = q->parent;
}
}
void search(node* & p,char a,node*& q)//搜索节点数据;
{
if (p->data == a)
q = p;
if (p->lnode != NULL)
search(p->lnode, a,q);
if (p->rnode != NULL)
search(p->rnode, a,q);
}
void search(node*& p, int n,node*& q,int m)//搜索相同权重的节点;
{
if (p->quan == n)
{
if (p->num > m&&p->data!='\0')
{
q = p;
m = p->num;
}
}
if (p->lnode != NULL)
search(p->lnode, n, q,m);
if (p->rnode != NULL)
search(p->rnode, n, q,m);
}
void fread(node* p)//测试是否正确的时候用来读取哈夫曼树各个节点的值,正是代码中可以删去
{
cout << endl;
if(p->data!='\0')
cout << p->data << ":" << p->quan << endl;
if (p->rnode != NULL)
{
fread(p->rnode);
}
if (p->lnode != NULL)
{
fread(p->lnode);
}
}
void pencoding()
{
}
node* gettr()
{
return tr;
}
};
int main()
{
int a[26] = { 0 };
char c;
int num=0;
trees L;
tree T;
ifstream fp;
ofstream ff;
ff.open("动态哈夫曼编码结果.txt");
ff.close();
fp.open("myfile.txt", ios::in);
fp >> c;//动态哈夫曼树建立——每读出一个字符就将该字符添加到哈夫曼树中
cout << "动态哈夫曼编码:" << endl;
if (fp.is_open())
{
cout << "success" << endl;
}
while (!fp.eof())
{
if (fp.good())
{
a[c - 'a']++;
T.creat(c);
fp >> c;
num++;
}
}
fp.close();
cout << endl;
for (int i = 0; i < 26; i++)//建立哈夫曼树
{
if (a[i] != 0)
{
L.create(i, a[i]);
}
}
// T.fread(T.gettr());//测试读出动态哈夫曼树,可删去。
// L.kl(L.gethead()->next);//测试输出哈夫曼树,可删去。
//哈夫曼编码:
cout << "哈夫曼编码:" << endl;
L.encoding();
L.lencoding();
//哈夫曼编码压缩:
hyasuo();
cout << "原文本字符数: " << num << endl;
//解压缩
hjieyasuo();
//哈夫曼译码:
cout << "原文本内容:" << endl;
ifstream fd;
fd.open("myfile.txt");
fd >> c;
while (!fd.eof())
{
if (fd.good())
{
cout << c;
fd >> c;
}
}
cout << endl;
cout << "哈夫曼译码结果:" << endl;
L.pencoding();
//cout << endl;
//cout << "动态哈夫曼译码结果:" << endl;
//T.pencoding();
return 0;
}
void hyasuo()
{
int i = 0,j=0,k;
char c;
ifstream fp;
ofstream ff;
ff.open("哈夫曼编码压缩后的信息.txt");
fp.open("哈夫曼编码结果.txt");
fp >> c;
i++;
while (!fp.eof())
{
int l = pow(2, i - 1);
j +=( c - '0')*l;
if (i == 6)
{
char d = (char)j;
i = 0;
ff << d;
k = d;
j = 0;
}
fp >> c;
i++;
}
if (i !=0)
{
char d = (char)j;
ff << d;
k = d;
}
i--;
int ch = '0' + i;
ff << i;
ff.close();
fp.close();
}
void hjieguo()
{
ifstream ff;
ff.open("哈夫曼编码压缩后的信息.txt");
char c;
while (!ff.eof())
{
ff >> c;
cout << c;
}
}
void hjieyasuo()
{
ofstream ff,ft;
ifstream fp;
int j = 0,m;
fp.open("哈夫曼编码压缩后的信息.txt");
ff.open("哈夫曼编码解压后的信息.txt");
ft.open("哈夫曼编码解压后修正的信息.txt");
char c;
fp >> c;
while (!fp.eof())
{
int i = (int)c;
m = c - '0';
for (int j = 0; j <6; j++)
{
ff << i % 2;
i = i /2;
}
j++;
fp >> c;
}
cout << "压缩后文本字符数:" << j << endl;
ff.close();
fp.close();
ifstream g;
g.open("哈夫曼编码解压后的信息.txt");
for (int k = 0; k < 6 * (j - 2) +m ; k++)
{
char x;
g >> x;
ft << x;
}
g.close();
ft.close();
}