huffman树

还存在缺陷
   //数据结构实验
//2018.3.21  lee
//哈夫曼编码译码

/*
愚蠢的初步思路:利用数组对字符进行计数,数组长度为ASCII码的额个数。 `
再利用数组中数量非零的ASCII码,构建哈夫曼树,再读哈夫曼树,输出编码;
同理,读取哈夫曼文件时通过判等确定对应的字符,写入另一文件,最后输出。
改进:将数组换为类,可以用链表存储,用一个哨位结点指向未被排序的最小weight节点
      排序可以用链表存储地址;
   实际构建Huffman树用Huffman结点

*/

#include<iostream>
#include<string>                                  //字符类型头文件
#include<fstream>
#include"stdio.h"
#include"stdlib.h"
using namespace std;
/*class node{
 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;
  }
};
class LLnode{                               //链表节点
 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();
  }
};
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){        //删除哈夫曼树 , 链表处删除各结点
  } */
 
};
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 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;
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值