还存在缺陷
//数据结构实验
//2018.3.21 lee
//哈夫曼编码译码
//2018.3.21 lee
//哈夫曼编码译码
/*
愚蠢的初步思路:利用数组对字符进行计数,数组长度为ASCII码的额个数。 `
再利用数组中数量非零的ASCII码,构建哈夫曼树,再读哈夫曼树,输出编码;
同理,读取哈夫曼文件时通过判等确定对应的字符,写入另一文件,最后输出。
改进:将数组换为类,可以用链表存储,用一个哨位结点指向未被排序的最小weight节点
排序可以用链表存储地址;
实际构建Huffman树用Huffman结点
排序可以用链表存储地址;
实际构建Huffman树用Huffman结点
*/
#include<iostream>
#include<string> //字符类型头文件
#include<fstream>
#include"stdio.h"
#include"stdlib.h"
using namespace std;
/*class node{
char c;
string s;
};*/
char c;
string s;
};*/
class HtreeNode{ //Huffman树节点
public:
int weight;
string code; //叶子节点的编码
int codep; //内节点代表0/1
HtreeNode* right;
HtreeNode* left;
char str;
HtreeNode(){
weight=0;
/*code=NULL;
codep=NULL;*/
right=NULL;
left=NULL;
}
};
public:
int weight;
string code; //叶子节点的编码
int codep; //内节点代表0/1
HtreeNode* right;
HtreeNode* left;
char str;
HtreeNode(){
weight=0;
/*code=NULL;
codep=NULL;*/
right=NULL;
left=NULL;
}
};
class LLnode{ //链表节点
public:
HtreeNode* point;
LLnode* next;
LLnode(){
HtreeNode* point=NULL;
LLnode* next=NULL;
}
~LLnode(){
//delete point; //析构删除结点 ,不能删吗? 不能,删了会出错;
point=NULL;
next=NULL;
}
};
public:
HtreeNode* point;
LLnode* next;
LLnode(){
HtreeNode* point=NULL;
LLnode* next=NULL;
}
~LLnode(){
//delete point; //析构删除结点 ,不能删吗? 不能,删了会出错;
point=NULL;
next=NULL;
}
};
class Hlinklist{ //链表
public:
LLnode* top;
int length;
Hlinklist(){
top=NULL;
length=0;
}
void firstlist(){ //构造函数
length=0;
LLnode* p1=new LLnode;
LLnode* p2;
char ch=' ';
top=p1;
p1->point=new HtreeNode; //创建一个新的Huffman结点
p1->point->str=ch;
for(int i=0;i<95;i++){
p2=new LLnode;
p2->point=new HtreeNode;
ch++;
p2->point->str=ch;
// cout<<p2->point->str<<endl;
p1->next=p2;
p1=p2;
}
cout<<"hdjkhfjkshfhd"<<endl;
}
void select(){ //删除无意义的结点
LLnode* p1=top; //先清除weight为零的节点
LLnode* p2;
while(top->point->weight==0){
p1=top;
top=top->next;
delete p1->point;
delete p1;
}
p1=top;
while(p1->next!=NULL){
p2=p1->next;
int w=p2->point->weight;
if(w==0){
p1->next=p2->next;
delete p2->point;
delete p2;
}
else p1=p1->next;
}
p1=top;
while(p1!=NULL){
int w=p1->point->weight;
cout<<w<<endl;
p1=p1->next;
}
}
/* int count(){ //计算链表长度,没用了,改想法啦
LLnode* p1=top;
while(p1!=NULL){
length++;
p1=p1->next;
}
}
*/
void rank(){ //链表按节点权重排序;
bool flag;
LLnode* p1=top;
LLnode* p2=p1->next;
if(p1->point->weight>p2->point->weight){
p1->next=p2->next;
p2->next=p1;
top=p2;
}
p1=top;
LLnode* p3;
flag=true;
while(flag){
flag=false;
while(p1->next->next!=NULL){
p2=p1->next;
p3=p2->next;
if(p2->point->weight>p3->point->weight){
p2->next=p3->next;
p3->next=p2;
p1->next=p3;
p1=p3;
flag=true;
}
else p1=p1->next;
}
}
/*p1=top;
while(p1!=NULL){
int w=p1->point->weight;
cout<<w<<endl;
p1=p1->next;
}*/
}
~Hlinklist(){ //析构函数
LLnode* p1;
while(top!=NULL){
p1=top;
top=top->next;
delete p1;
}
}
HtreeNode* creatHtree(){ //创建Huffman树
LLnode* p1;
LLnode* p2;
while(top->next!=NULL){
rank();
p1=top;
p2=top->next;
LLnode* p3=new LLnode; //创建新节点
p3->point=new HtreeNode;
p3->point->weight=p2->point->weight+p1->point->weight; //哈夫曼结点逐渐成为树
p3->point->left=p1->point;
p3->point->right=p2->point;
p3->next=p2->next;
top=p3;
p3=NULL;
delete p1;
delete p2;
}
cout<<top->point->weight<<endl;
return top->point;
}
void creatlist(){ //从文件读入文字,创建对应的链表
fstream f1;
f1.open("f1.txt",ios::in|ios::out|ios::app);
char ch;
f1>>noskipws;
while(!f1.eof()){
length++;
f1>>ch;
//cout<<ch<<endl; //输出字符
LLnode* p1=top;
while(ch!=p1->point->str&&p1!=NULL) p1=p1->next;
p1->point->weight ++;
}
LLnode* p1=top;
while(p1!=NULL){
int w=p1->point->weight;
//cout<<w<<endl; //输出权重
p1=p1->next;
}
f1.close();
}
};
LLnode* top;
int length;
Hlinklist(){
top=NULL;
length=0;
}
void firstlist(){ //构造函数
length=0;
LLnode* p1=new LLnode;
LLnode* p2;
char ch=' ';
top=p1;
p1->point=new HtreeNode; //创建一个新的Huffman结点
p1->point->str=ch;
for(int i=0;i<95;i++){
p2=new LLnode;
p2->point=new HtreeNode;
ch++;
p2->point->str=ch;
// cout<<p2->point->str<<endl;
p1->next=p2;
p1=p2;
}
cout<<"hdjkhfjkshfhd"<<endl;
}
void select(){ //删除无意义的结点
LLnode* p1=top; //先清除weight为零的节点
LLnode* p2;
while(top->point->weight==0){
p1=top;
top=top->next;
delete p1->point;
delete p1;
}
p1=top;
while(p1->next!=NULL){
p2=p1->next;
int w=p2->point->weight;
if(w==0){
p1->next=p2->next;
delete p2->point;
delete p2;
}
else p1=p1->next;
}
p1=top;
while(p1!=NULL){
int w=p1->point->weight;
cout<<w<<endl;
p1=p1->next;
}
}
/* int count(){ //计算链表长度,没用了,改想法啦
LLnode* p1=top;
while(p1!=NULL){
length++;
p1=p1->next;
}
}
*/
void rank(){ //链表按节点权重排序;
bool flag;
LLnode* p1=top;
LLnode* p2=p1->next;
if(p1->point->weight>p2->point->weight){
p1->next=p2->next;
p2->next=p1;
top=p2;
}
p1=top;
LLnode* p3;
flag=true;
while(flag){
flag=false;
while(p1->next->next!=NULL){
p2=p1->next;
p3=p2->next;
if(p2->point->weight>p3->point->weight){
p2->next=p3->next;
p3->next=p2;
p1->next=p3;
p1=p3;
flag=true;
}
else p1=p1->next;
}
}
/*p1=top;
while(p1!=NULL){
int w=p1->point->weight;
cout<<w<<endl;
p1=p1->next;
}*/
}
~Hlinklist(){ //析构函数
LLnode* p1;
while(top!=NULL){
p1=top;
top=top->next;
delete p1;
}
}
HtreeNode* creatHtree(){ //创建Huffman树
LLnode* p1;
LLnode* p2;
while(top->next!=NULL){
rank();
p1=top;
p2=top->next;
LLnode* p3=new LLnode; //创建新节点
p3->point=new HtreeNode;
p3->point->weight=p2->point->weight+p1->point->weight; //哈夫曼结点逐渐成为树
p3->point->left=p1->point;
p3->point->right=p2->point;
p3->next=p2->next;
top=p3;
p3=NULL;
delete p1;
delete p2;
}
cout<<top->point->weight<<endl;
return top->point;
}
void creatlist(){ //从文件读入文字,创建对应的链表
fstream f1;
f1.open("f1.txt",ios::in|ios::out|ios::app);
char ch;
f1>>noskipws;
while(!f1.eof()){
length++;
f1>>ch;
//cout<<ch<<endl; //输出字符
LLnode* p1=top;
while(ch!=p1->point->str&&p1!=NULL) p1=p1->next;
p1->point->weight ++;
}
LLnode* p1=top;
while(p1!=NULL){
int w=p1->point->weight;
//cout<<w<<endl; //输出权重
p1=p1->next;
}
f1.close();
}
};
class Htree{ //Huffman树
public:
HtreeNode* root;
LLnode* top;
string s;
string ss_de;
string decodes;
Htree(){
root=NULL;
top=NULL;
decodes.erase();
}
void Htreecode(){ //输出各字符编码,编好huffman树的编码;
if(root==NULL) cout<<"Huffman树暂未构造"<<endl;
HtreeNode* p1=root;
firstroot(root);
}
void firstroot(HtreeNode* item){
if(item->left!=NULL){
item->left->codep=0;
if(item->code.empty()) item->left->code='0';
else item->left->code=item->code+'0';
firstroot(item->left);
}
if(item->right!=NULL){
item->right->codep=1;
if(item->code.empty()) item->right->code='1';
item->right->code=item->code+'1';
firstroot(item->right);
}
if(item->left==NULL&&item->right==NULL){
cout<<item->str<<':'<<item->code<<endl;
LLnode* p1=new LLnode;
p1->point=item;
if(top==NULL) top=p1;
else{
p1->next=top;
top=p1;
}
// cout<<top->point->code<<endl;
return;
}
}
void huffstring(){ //记录字符串
fstream f1;
s.erase() ;
f1.open("f1.txt",ios::in|ios::out|ios::app);
int d;
char ch;
HtreeNode* it;
f1>>noskipws;
LLnode* p1;
while(!f1.eof()){
f1>>ch;
p1=top;
string s1;
while(p1!=NULL){
if(p1->point->str==ch){
s1=p1->point->code;
s+=s1;
// cout<<s<<endl;
break;
}
else p1=p1->next;
}
}
f1.close();
return;
//f2.close();
}
void Huffcode(){ //将编码写入二进制文件
huffstring();
FILE* f2;
f2=fopen("f2.huf","wb");
char c;
for(int i=0;i<s.length();i++){
if(s[i]=='0') c=(c<<1)|1;
else c=c<<1;
if((i+1)%8==0) {
fwrite(&c,sizeof(char),1,f2);
char c;
}
}
int x=(s.length()+1)%8;
if(x!=0){
for(int i=0;i<8-x;i++) c=(c<<1)|1;
fwrite(&c,sizeof(char),1,f2);
}
fclose(f2);
}
int read(int i,HtreeNode* item){
if(item->left==NULL&&item->right==NULL){
decodes+=item->str;
return i;
}
if(ss_de[i]=='0'){
i++;
read(i,item->left);
}
else{
i++;
read(i,item->right);
}
}
void decode_string(){ //译码,根据输入的二进制码输出字符串
char c;
ss_de.erase();
FILE *f1;
f1=fopen("f2.huf","rb");
while(!feof(f1)){
c=getc(f1);
char d;
for(int i=0;i<8;i=i+1){
d=c<<i;
d=d>>7;
if(int(d)==0){
ss_de+='0';
}
if(int(d)==-1){
ss_de+='1';
}
}
}
fclose(f1);
}
void decode(){
decode_string();
int j=0;
while(j<ss_de.length()){
j=read(j,root);
}
fstream f1;
f1.open("f3.txt",ios::in|ios::out|ios::app);
f1<<decodes;
f1.close();
}
/*void deleteH(HtreeNode* item){ //删除哈夫曼树 , 链表处删除各结点
} */
};
public:
HtreeNode* root;
LLnode* top;
string s;
string ss_de;
string decodes;
Htree(){
root=NULL;
top=NULL;
decodes.erase();
}
void Htreecode(){ //输出各字符编码,编好huffman树的编码;
if(root==NULL) cout<<"Huffman树暂未构造"<<endl;
HtreeNode* p1=root;
firstroot(root);
}
void firstroot(HtreeNode* item){
if(item->left!=NULL){
item->left->codep=0;
if(item->code.empty()) item->left->code='0';
else item->left->code=item->code+'0';
firstroot(item->left);
}
if(item->right!=NULL){
item->right->codep=1;
if(item->code.empty()) item->right->code='1';
item->right->code=item->code+'1';
firstroot(item->right);
}
if(item->left==NULL&&item->right==NULL){
cout<<item->str<<':'<<item->code<<endl;
LLnode* p1=new LLnode;
p1->point=item;
if(top==NULL) top=p1;
else{
p1->next=top;
top=p1;
}
// cout<<top->point->code<<endl;
return;
}
}
void huffstring(){ //记录字符串
fstream f1;
s.erase() ;
f1.open("f1.txt",ios::in|ios::out|ios::app);
int d;
char ch;
HtreeNode* it;
f1>>noskipws;
LLnode* p1;
while(!f1.eof()){
f1>>ch;
p1=top;
string s1;
while(p1!=NULL){
if(p1->point->str==ch){
s1=p1->point->code;
s+=s1;
// cout<<s<<endl;
break;
}
else p1=p1->next;
}
}
f1.close();
return;
//f2.close();
}
void Huffcode(){ //将编码写入二进制文件
huffstring();
FILE* f2;
f2=fopen("f2.huf","wb");
char c;
for(int i=0;i<s.length();i++){
if(s[i]=='0') c=(c<<1)|1;
else c=c<<1;
if((i+1)%8==0) {
fwrite(&c,sizeof(char),1,f2);
char c;
}
}
int x=(s.length()+1)%8;
if(x!=0){
for(int i=0;i<8-x;i++) c=(c<<1)|1;
fwrite(&c,sizeof(char),1,f2);
}
fclose(f2);
}
int read(int i,HtreeNode* item){
if(item->left==NULL&&item->right==NULL){
decodes+=item->str;
return i;
}
if(ss_de[i]=='0'){
i++;
read(i,item->left);
}
else{
i++;
read(i,item->right);
}
}
void decode_string(){ //译码,根据输入的二进制码输出字符串
char c;
ss_de.erase();
FILE *f1;
f1=fopen("f2.huf","rb");
while(!feof(f1)){
c=getc(f1);
char d;
for(int i=0;i<8;i=i+1){
d=c<<i;
d=d>>7;
if(int(d)==0){
ss_de+='0';
}
if(int(d)==-1){
ss_de+='1';
}
}
}
fclose(f1);
}
void decode(){
decode_string();
int j=0;
while(j<ss_de.length()){
j=read(j,root);
}
fstream f1;
f1.open("f3.txt",ios::in|ios::out|ios::app);
f1<<decodes;
f1.close();
}
/*void deleteH(HtreeNode* item){ //删除哈夫曼树 , 链表处删除各结点
} */
};
int menu(){
int i;
cout<<"-------------------------------------请输入要进行操作的选项---------------------------------------"<<endl;
cout<<"---------------------------------------1.查看Huffman编码------------------------------------------"<<endl;
cout<<"---------------------------------------2.编码-----------------------------------------------------"<<endl;
cout<<"---------------------------------------3.译码-----------------------------------------------------"<<endl;
cout<<"---------------------------------------4.查看压缩率-----------------------------------------------"<<endl;
cout<<"---------------------------------------5.退出-----------------------------------------------------"<<endl;
cin>>i;
return i;
}
int i;
cout<<"-------------------------------------请输入要进行操作的选项---------------------------------------"<<endl;
cout<<"---------------------------------------1.查看Huffman编码------------------------------------------"<<endl;
cout<<"---------------------------------------2.编码-----------------------------------------------------"<<endl;
cout<<"---------------------------------------3.译码-----------------------------------------------------"<<endl;
cout<<"---------------------------------------4.查看压缩率-----------------------------------------------"<<endl;
cout<<"---------------------------------------5.退出-----------------------------------------------------"<<endl;
cin>>i;
return i;
}
int main(){
Hlinklist hl;
hl.firstlist();
hl.creatlist();
hl.select();
Htree ht/*(hl.count())*/;
ht.root=hl.creatHtree();
int i=menu();
system("cls");
while(i!=5){
int i=menu();
switch(i){
case 1:{
ht.Htreecode();
system("pause");
system("cls");
break;
}
case 2:{
ht.Huffcode();
system("pause");
system("cls");
break;
}
case 3:{
// ht.decode();
system("pause");
system("cls");
break;
}
case 4:{
int x=ht.s.length();
int y=hl.length*8;
float z=(x*1.0)/(y*1.0);
cout<<z<<endl;
system("pause");
system("cls");
break;
}
case 5:{
i=5;
break;
}
default:
cout<<"输入错误,请重新输入..."<<endl;
}
}
return 0;
}
Hlinklist hl;
hl.firstlist();
hl.creatlist();
hl.select();
Htree ht/*(hl.count())*/;
ht.root=hl.creatHtree();
int i=menu();
system("cls");
while(i!=5){
int i=menu();
switch(i){
case 1:{
ht.Htreecode();
system("pause");
system("cls");
break;
}
case 2:{
ht.Huffcode();
system("pause");
system("cls");
break;
}
case 3:{
// ht.decode();
system("pause");
system("cls");
break;
}
case 4:{
int x=ht.s.length();
int y=hl.length*8;
float z=(x*1.0)/(y*1.0);
cout<<z<<endl;
system("pause");
system("cls");
break;
}
case 5:{
i=5;
break;
}
default:
cout<<"输入错误,请重新输入..."<<endl;
}
}
return 0;
}